I am implementing a NxN puzzle solver using A* search algorithm and using Manhattan distance as a heuristic and I've run into a curious bug (?) which I can't wrap my head around.
Consider these puzzles (0 element being blank space):
(initial)
1 0 2
7 5 4
8 6 3
(goal)
1 2 3
4 5 6
7 8 0
The minumum number of moves to reach solution from initial state is 11. However, my solver, reaches goal in 17 moves.
And therein lies the problem - my puzzle solver mostly solves the solvable puzzles in a correct (minimum) number of moves but for this particular puzzle, my solver overshoots the minimum number of moves and I think I've nailed down the problem to a miscalculation of Manhattan distance in this particular case.
At this link you can see what my solver is doing (on the right) and what a tried-n-tested solver is doing (Brian Borowski's excellent solver, available here).
In the very first move, Brian's solver immediately chooses solution that pushes element 5 up, but my solver has other ideas, and on the stacktrace (given on the link), my solver chooses solution which pushes 2 to the left (since that board's Manhattan distance is lower, the board is on the front of priority queue).
I can't see what is the problem and I can't blame my Manhattan distance calculation, since it correctly solves a number of other 3x3 puzzles.
Here is how I calculate the Manhattan distance of a given Board:
/**
* Calculates sum of Manhattan distances for this board and stores it in private field to promote immutability.
*/
private void calculateManhattanDistance() {
int manhattanDistanceSum = 0;
for (int x = 0; x < N; x++) // x-dimension, traversing rows (i)
for (int y = 0; y < N; y++) { // y-dimension, traversing cols (j)
int value = tiles[x][y]; // tiles array contains board elements
if (value != 0) { // we don't compute MD for element 0
int targetX = (value - 1) / N; // expected x-coordinate (row)
int targetY = (value - 1) % N; // expected y-coordinate (col)
int dx = x - targetX; // x-distance to expected coordinate
int dy = y - targetY; // y-distance to expected coordinate
manhattanDistanceSum += Math.abs(dx) + Math.abs(dy);
}
}
manhattanDistance = manhattanDistanceSum;
}
I would appreciate any insight or idea you may have.
If any additional code is needed, I'll post it right away.
I was stuck in the same place sometime back where I was solving this in 17 moves.The problem was that I was only using heuristic h(n) for the A* algorithm and whereas for choosing the next node A* uses manhattan distance(heuristic) + pathcost (cost to reach the node from root called as g(n)) to make the choice.
Once you plug in this to the algorithm it works like a charm.
Hope this helps someone who is stuck in the same place.
If your heuristic it's admissible (and it is, check this) than A* always return optimal solution. Can be slower or faster (expand more or less nodes) but it returns the optimal solution.
So, cause your heuristic is admissible the problem must be in A* algorithm implementation.
In addition the fact that its first step it's different from the optimal one is meaningless: the algorithm can correctly performs backtrace to get the correct solution path in the future. All the open nodes are candidates for the next step, not only the child of the current node.
Related
I need a fast way to find maximum value when intervals are overlapping, unlike finding the point where got overlap the most, there is "order". I would have int[][] data that 2 values in int[], where the first number is the center, the second number is the radius, the closer to the center, the larger the value at that point is going to be. For example, if I am given data like:
int[][] data = new int[][]{
{1, 1},
{3, 3},
{2, 4}};
Then on a number line, this is how it's going to looks like:
x axis: -2 -1 0 1 2 3 4 5 6 7
1 1: 1 2 1
3 3: 1 2 3 4 3 2 1
2 4: 1 2 3 4 5 4 3 2 1
So for the value of my point to be as large as possible, I need to pick the point x = 2, which gives a total value of 1 + 3 + 5 = 9, the largest possible value. It there a way to do it fast? Like time complexity of O(n) or O(nlogn)
This can be done with a simple O(n log n) algorithm.
Consider the value function v(x), and then consider its discrete derivative dv(x)=v(x)-v(x-1). Suppose you only have one interval, say {3,3}. dv(x) is 0 from -infinity to -1, then 1 from 0 to 3, then -1 from 4 to 6, then 0 from 7 to infinity. That is, the derivative changes by 1 "just after" -1, by -2 just after 3, and by 1 just after 6.
For n intervals, there are 3*n derivative changes (some of which may occur at the same point). So find the list of all derivative changes (x,change), sort them by their x, and then just iterate through the set.
Behold:
intervals = [(1,1), (3,3), (2,4)]
events = []
for mid, width in intervals:
before_start = mid - width - 1
at_end = mid + width
events += [(before_start, 1), (mid, -2), (at_end, 1)]
events.sort()
prev_x = -1000
v = 0
dv = 0
best_v = -1000
best_x = None
for x, change in events:
dx = x - prev_x
v += dv * dx
if v > best_v:
best_v = v
best_x = x
dv += change
prev_x = x
print best_x, best_v
And also the java code:
TreeMap<Integer, Integer> ts = new TreeMap<Integer, Integer>();
for(int i = 0;i<cows.size();i++) {
int index = cows.get(i)[0] - cows.get(i)[1];
if(ts.containsKey(index)) {
ts.replace(index, ts.get(index) + 1);
}else {
ts.put(index, 1);
}
index = cows.get(i)[0] + 1;
if(ts.containsKey(index)) {
ts.replace(index, ts.get(index) - 2);
}else {
ts.put(index, -2);
}
index = cows.get(i)[0] + cows.get(i)[1] + 2;
if(ts.containsKey(index)) {
ts.replace(index, ts.get(index) + 1);
}else {
ts.put(index, 1);
}
}
int value = 0;
int best = 0;
int change = 0;
int indexBefore = -100000000;
while(ts.size() > 1) {
int index = ts.firstKey();
value += (ts.get(index) - indexBefore) * change;
best = Math.max(value, best);
change += ts.get(index);
ts.remove(index);
}
where cows is the data
Hmmm, a general O(n log n) or better would be tricky, probably solvable via linear programming, but that can get rather complex.
After a bit of wrangling, I think this can be solved via line intersections and summation of function (represented by line segment intersections). Basically, think of each as a triangle on top of a line. If the inputs are (C,R) The triangle is centered on C and has a radius of R. The points on the line are C-R (value 0), C (value R) and C+R (value 0). Each line segment of the triangle represents a value.
Consider any 2 such "triangles", the max value occurs in one of 2 places:
The peak of one of the triangle
The intersection point of the triangles or the point where the two triangles overall. Multiple triangles just mean more possible intersection points, sadly the number of possible intersections grows quadratically, so O(N log N) or better may be impossible with this method (unless some good optimizations are found), unless the number of intersections is O(N) or less.
To find all the intersection points, we can just use a standard algorithm for that, but we need to modify things in one specific way. We need to add a line that extends from each peak high enough so it would be higher than any line, so basically from (C,C) to (C,Max_R). We then run the algorithm, output sensitive intersection finding algorithms are O(N log N + k) where k is the number of intersections. Sadly this can be as high as O(N^2) (consider the case (1,100), (2,100),(3,100)... and so on to (50,100). Every line would intersect with every other line. Once you have the O(N + K) intersections. At every intersection, you can calculate the the value by summing the of all points within the queue. The running sum can be kept as a cached value so it only changes O(K) times, though that might not be posible, in which case it would O(N*K) instead. Making it it potentially O(N^3) (in the worst case for K) instead :(. Though that seems reasonable. For each intersection you need to sum up to O(N) lines to get the value for that point, though in practice, it would likely be better performance.
There are optimizations that could be done considering that you aim for the max and not just to find intersections. There are likely intersections not worth pursuing, however, I could also see a situation where it is so close you can't cut it down. Reminds me of convex hull. In many cases you can easily reduce 90% of the data, but there are cases where you see the worst case results (every point or almost every point is a hull point). For example, in practice there are certainly causes where you can be sure that the sum is going to be less than the current known max value.
Another optimization might be building an interval tree.
Problem 15:
Starting in the top left corner of a 2×2 grid, there are 6 routes (without backtracking) to the bottom right corner.
How many routes are there through a 20×20 grid?
So my attempt at Problem 15 is kinda bruteforcy because I try to get permutations of all of the possible valid paths by going from right to left and changing the predecessor of the first change of direction. For example, when I have a 2x2 grid (look at the Problem 15 link graphics) the first path I'll take is right - right - down - down and the last one I'll take is down - down - right - right, which is also my termination criteria. I add the possible valid paths into a list and also use that list to determine whether the valid path has been already added or not. And to permutate a path I'll do what I've mentioned earlier: I go from right to left in my array (Which in the graphic would be the bottom right corner where the arrowhead points at) and change the first element of which the next element is different from itself. So right - right - down - down would become right - right - right - down, which is obviously invalid since you have to have the same amount of rights and downs to be able to reach the end corner. So what I thought is to make another loop going from left to right and change as many elements as needed to get a valid path. So in this example right - right - right - down becomes down - right - right - down.
Also, what I forgot is that I'm not counting the points, I'm counting the edges from top left corner to bottom right corner.
So I have already written some code, but it doesn't work at all.
package projecteuler;
import java.util.ArrayList;
public class Projecteuler {
public static final int GRIDSIZE = 2;
public static void main(String[] args) {
ArrayList<boolean[]> paths = new ArrayList<>();
paths.add(new boolean[GRIDSIZE * 2]);
for(int i = 0; i < GRIDSIZE; i++) {
paths.get(0)[i] = true;
paths.get(0)[GRIDSIZE * 2 - 1 - i] = false;
}
boolean[] buf = paths.get(0).clone();
printArr(buf);
boolean tmp;
while(!checkTerminate(paths)) {
while(paths.contains(buf)) {
tmp = buf[buf.length - 1];
for(int i = buf.length - 1; buf[i - 1] != tmp && 0 < i; i--) {
buf[i] = !buf[i];
for(int j = 0; checkValid(buf) && j < i; j++)
buf[j] = !buf[j];
}
}
paths.add(buf.clone());
printArr(buf);
}
System.out.println(paths.size());
}
public static boolean checkTerminate(ArrayList<boolean[]> paths) {
boolean[] endPath = new boolean[GRIDSIZE * 2];
for(int i = 0; i < GRIDSIZE; i++) {
endPath[i] = false;
endPath[GRIDSIZE * 2 - 1 - i] = true;
}
return paths.contains(endPath);
}
public static boolean checkValid(boolean[] arr) {
int countR = 0,
countL = 0;
for(int i = 0; i < arr.length; i++)
if(arr[i])
countR++;
else
countL++;
return countR == countL;
}
public static void printArr(boolean[] arr) {
for(int i = 0; i < arr.length; i++)
System.out.print(arr[i] ? "right " : "down ");
System.out.println();
}
}
It somehow doesn't change anything anywhere.
right right down down
right right down down
right right down down
right right down down ...
and so on is all it's outputting. It seems that the code simply doesn't permutate my path, but also doesn't get stuck in any of the for loops. My best guess would be that my function criteria are placed in the wrong sequence
I also thought of a solution with backtracking like we did for a labyrinth two years ago in school, but I want to see if this approach is anywhere viable or not before redoing everything.
EDIT:
I'll try to implement the images of the 2 x 2 grid example asap, but the ProjectEuler website is under maintainance at the moment.
The solution is given by the number of combinations of "down" and "right" movements we can have. Since there is no backtracking, there are N downwards and N rightwards movements in total (in any route, for an NxN grid). There are 2N movements in total.
We can obtain this using the binomial coefficient, nCr (pronounced "n choose r"), which is the number of ways of choosing r objects from n objects (each of which can be two things). In our case an "object" is either a downward or rightward movement. This is given by
Thus the number we want is:
For N = 2 this gives 6. For N = 20 this gives 137846528820.
Let a step in right be termed as R and a step down is termed as D.
In order to reach from top-left to bottom-right on a n rows and m column grid, you will have to go right m times and go down n times.
Essentially, you will have to get all the possible arrangements of m R's and n D's.
Example: For a 2 by 2 grid, the number of unique permutations of the word RRDD will be the number of ways in which you can go, viz.
RRDD
RDRD
DRDR
DDRR
Google the formula to calculate the permutations of letters with repetition, which is given by:
n! / ( r1! * r2! ... ), where sum of all r's is n.
This question on Math SE pops up first when looking for repetitive letter permutation count, and the second answer explains better in my opinion.
So, to return the count AND even to return the paths, you don't need to traverse the maze at all. Just do the formula calculation for first one and print the permutations for second problem.
Giving the paths when certain steps are off grid will be the only case that requires you to actually traverse the maze.
UPDATE:
It helps to visualize the formula for permutation of repeated letters.
Here is a slide that demonstrates that case. See how the 2 E's end up duplicating the arrangements when generating the permutations. In general, any letter that's repeated r times will cause r! duplication because wherever in the arrangement that letter is put, it can be replaced with another same letter without giving a new permutation.
That way, if we divide the total n! permutations with r!, we get the actual unique permutations.
Image Source
i am writing the function to check if the given value is included in the matrix in . This matrix has the following properties:
•Integers in each row are sorted in ascending from left to right.
•Integers in each column are sorted in ascending from top to bottom
public static boolean searchMatrix(int target, int[][] matrix)
{
for(int i = 0;i <= matrix[0].length;i++)
{
for (int j=i; j<matrix.length;j++)
{
if(target == matrix[i][j])
return true;
}
}
return false;
}
i want to know weather this program has time complexity of O(N).
if not what changes should i make to get into O(N).
I think the search can be done in linear time. Consider the following 4×4 matrix as a visual:
1 2 4 6
2 3 5 7 ascending from left to right
3 4 6 8 and from top to bottom
4 5 6 9
If we were searching for the value 5 we could begin in the upper left, and then walk to the right until we have either found the value, or encountered a number which is greater than the target of 5. In this case, we hit 6. Then, we can rollback to 4, and advance down to a higher row. It is guaranteed that every previous value in the first row is less than the target and that every value in the next row from that column onwards is greater than the value on the first row.
This is a roughly linear approach. A good analogy would be walking around the perimeter of a mountain, looking for a certain elevation. If at each spot we either don't find the height we want, or find only points too high, we keep walking.
The way you have it written (brute force computation) has a worst case time complexity of O(N^2). Since you say that the arrays are sorted, you can instead implement binary search which will have a worst case time complexity of N(2*log(N)).
Assuming a n x m matrix, your algorithm is O(n * m), because it (potentially) iterates all rows and columns (ie all elements).
However, there exists an algorithm that is O(log(m + n)).
Because this is for an on-line coding interview (I am psychic), I will give you hints only:
Given elements at coordinate (x, y), what can know about where the target might be?
What could you do if you treated x and y separately?
you say the matrix is sorted ,may you can use binary search to find the target . and use two individual one layer loop , firstly search row ,then column.it's o(N/2).
As stated your algorithm is O(N*M) or O(N^2) for a square matrix.
You can do it with a single loop:
Basically starting from the top right you check the cell if the number is too big move left if the number is too small move down. If you fall off the edge on either side the number's not there.
boolean searchMatrix(int target, int[][] mat)
{
int i = 0, j = mat[0].length;
while (i < mat.length && j >= 0)
{
if (mat[i][j] == target)
{
return true;
}
else if (mat[i][j] < target)
{
i++;
}
else
{
j--;
}
}
return false;
}
I am using a 2 dimensional boolean array to check where an entity is inside of my 2D side scroller as well as for collision. I know I am not looking for how high or low an entity away is and that is intentional. When I run this code it says the closest entity is 15 cells away. However, when I run my code it says the closest entity away is 15 blocks. Also when I print out distanceX it prints out the following:
9
0
0
2
2
15
9
0
0
2
2
15. I don't know why it won't register 9 as the closest even though that's is the first closest distance it recieves.
I can't post pictures yet however the reason 0,0,2, and 2 get printed is because I have 4 rectangles in all four corners of my player that are considered true in the grid so it detects the two on top of eachother and the other 2 or 2 spots away in the grid. Since I cant upload pictures try to see what I mean with this image i made. https://lh3.googleusercontent.com/OLSDPshjeU0YMahcmc0MDk-NocBMoG-7iN2xFTeFsQ8mAfF-sEPD8NBqXP4ENoN4YWmfUQ=s114
Thanks for any help!!
//Loop through my grid of booleans
for (int x = 0; x < map.getMapGrid().length; x++) {
for (int y = 0; y < map.getMapGrid().length; y++) {
//For comparison
Long distance = Long.MAX_VALUE;
// The second part of the if statement is to make sure it is checking for
// entities that arent the floor, therefor one above the grid position of the player
if (map.getMapGrid()[x][y] && y > ((Player) player).getGridPositionLeft().y - 1){
// distanceX = where something true was found (x) - where the player is in the grid
// Ex: 1 - 4 = |-3|, there is an entity 3 away
distanceX = Math.abs((int)(x - ((Player) player).getGridPositionLeft().x));
// if the distance of the entity from the player is less then the comparison variable,
// the closest entity x coordinate is distanceX
if(distanceX < distance){
closestCoord.x = distanceX;
closestCoord.y = 0;
}
}
}
}
return closestCoord;
}
Long distance = Long.MAX_VALUE;
This variable is never re-assigned, so it will always have the value Long.MAX_VALUE.
Also it is declared inside the innermost loop, so it will reset on each iteration. If you want the value of a variable to be remembered between iterations you need to declare and initialize it outside the loops.
I am trying to implement a 2 dimensional matrix as a maze. There is a starting point, an ending point (randomly chosen). And to make it little complicated, there are obstacles and agents. If the rat runs into an obstacle, it should backtrack and find the correct path. If it runs into an agent, it gets destroyed.
Here's a sample 4x4 matrix
1 7 1 1
2 1 1 0
1 0 1 0
1 1 1 9
Key: 0 is an obstacle, 2 is an agent, 7 is the starting point, 9 is the goal/ending point. 1 means that is is safe to move there.
The correct solution for this matrix would be:
0 1 1 0
0 0 1 0
0 0 1 0
0 0 1 1
But the rat is not intelligent (at least for this program) , so I am implementing a brute force algorithm, with random moves.
I have tried to implement this using a recursive function called mazeUtil().
Below is the function:
maze[][] is the randomized initial matrix that the rat moves through.
solution[][] is the solution matrix that will keep track of the moves.
(x, y) is the current position in the grid
n is the size of the matrix (it is a square matrix).
public static void mazeUtil(int maze[][], int solution[][], int x, int y, int n)
{
if(x == goal[0] && y == goal[1])
{
solution[x][y] = 1;
return;
}
int check = moveCheck(maze, x, y, n);
//moveCheck() return 0 for Obstacle, 1 for safe path, 2 for agent, 7 for starting point (also safe path), 9 for goal (safe path)
if (check == 2){
solution[x][y] = 1;
out.println("Oops! Ran into an agent!");
return;
}
else if(check == 0)
{
//What should I put here?
}
else if(check == 1 || check == 7 || check == 9)
{
solution[x][y] = 1;
Random newRandom = new Random();
int temp = newRandom.nextInt(3);
if(temp == 0){ //move up if possible? x--
if(x > 0)
mazeUtil(maze, solution, x-1, y, n);
else
mazeUtil(maze, solution, x+1, y, n);
}
else if (temp == 1){
if (x < n-1)
mazeUtil(maze, solution, x+1, y, n);
else
mazeUtil(maze, solution, x-1, y, n);
}
else if(temp == 2){
if (y < n-1)
mazeUtil(maze, solution, x, y+1, n);
else
mazeUtil(maze, solution, x,y-1, n);
}
else if (temp == 3){
if (y > 0)
mazeUtil(maze, solution, x, y-1, n);
else
mazeUtil(maze, solution, x, y+1, n);
}
}
}
I have to randomize the moves and that's why i have used random function. My function works quite well if it runs into an agent (2). I have also prevented the rat from going out of boundary. And it doesn't have any problem going through the safe path (1). But the problem is when it hits an obstacle. I'm thinking about backtracking. How do I add that into my function? Like save the last step, and do the reverse? And it is quite possible that there is no solution in the maze like this one
7 0 0 9
2 0 1 1
0 1 0 0
1 2 0 1
It would hit an obstacle if it goes right, and hit an agent if it goes down. It cannot move diagonally.
That brings me to my second question, how would I terminate my recursive function in that case.
At this point the only time it terminates is when it reaches the goal or hits an agent.
Any help would be appreciated. Thanks in advance
Well, let's imagine I need to solve the same problem by the same way you are solving it.
(I think the best solution for it is Path finding, as already mentioned in comments).
I will create
class Point{
public int x;
public int y;
}
and store coordinates in it.
I will store all points the rat visited in List<Point> path
In this solution you do not have problems with previous point (it is the last point in list)
As for algorithm termination -- you use algorithm with randoms. So you can't be sure that your rat will solve the simplest maze like
7 1 1
1 1 1
1 1 1
it is possible that rat will move from (0,0) to (1,0) and from (1,0) to (0,0) forever.
So, let's again imagine that I need to improve your algorithm instead of using good one.
I will store number of times the rat returned back from obstacle or visited the point in path list.
If this number > 4 I will command to my rat return back to the original point (point 7). And start the journey again.
If the rat need to return back, for example 10 times, the algorithm terminates.
Again, your algorithm is funny, and it should be interesting to see how the rat moves but it does not solve the problem. It will not work on big mazes.
Try to implement path finding. If you will have problems -- ask questions.
Good luck!
A quick point on style, to save some typing later: maze[][], solution[][] and n are all effectively global, and do not change between recursive calls (maze and solution are just passed as references to the same arrays, and n never changes). This is purely style, but you can write this as:
private static int[][] maze;
private static int[][] solution;
private static int n;
public static void mazeUtil(int x, int y) {
...
}
So on to your solution: the first point is I don't see how you know when you've reached the goal; your mazeUtil function does not return anything. For this kind of recursion, a general approach is for your solver function to return a boolean: true if the goal has been reached and false if not. Once you get a true, you just pass it back all the way up the call stack. Each time you get a false, you backtrack to the next solution.
So I'd suggest:
public static boolean mazeUtil(int x, int y) {
// return true if goal found, false otherwise
...
}
Next, I'm not sure what the practical difference between an agent and an obstacle is: running in to either causes you to backtrack. So I'd think that bit of code would be:
if (check == 2) {
out.println("Oops! Ran into an agent!");
return false;
}
if (check == 0)
out.println("Oops! Ran into an obstacle!");
return false;
}
Then the recursive bit: one point here is you do not ever reset the solution to 0 for failed attempts (actually, as the final algorithm will never backtrack more than a single step this is not actually that important, but it's good to illustrate the general approach). Given what we have so far, this should now be something like:
if (check == 9) {
out.println("Found the goal!");
return true;
}
if (check == 1 || check == 7) {
// add current position to solution
solution[x][y] = 1;
// generate random move within bounds
int nextX = ...
int nextY = ...
if (mazeUtil(nextX, nextY)) {
// we've found the solution, so just return up the call stack
return true;
}
// this attempt failed, so reset the solution array before returning
solution[x][y] = 0;
return false;
}
// shouldn't ever get here...
throw new IllegalStateException("moveCheck returned unexpected value: " + check);
Right, so far so good, but there's still a problem. As soon as one of the mazeUtil calls returns a value (either true or false) it will return that all the way up the calls stack. So if you happen to find the exit before an agent or an obstacle, all good, but that's quite unlikely. So instead of trying a single move when recursing, you need to try all possible moves.
WIth a supporting class Point, containing a simple x and y pair:
if (check == 1 || check == 7) {
// add current position to solution
solution[x][y] = 1;
// generate an array of all up/down/left/right points that are within bounds
// - for a random path need to randomise the order of the points
Point[] points = ...
for (Point next : points) {
if (mazeUtil(next.x, next.y)) {
// we've found the solution, so just return up the call stack
return true;
}
}
// this attempt failed, so reset the solution array before returning
solution[x][y] = 0;
return false;
}
And I think that's about as far as you can go with a totally ignorant rat! To see how this works, consider the following maze:
7 1
0 9
Starting at "7", possible moves are Down and Right.
If you try Down first, it returns false, so the only option left is
Right, so you end up on the "1".
If you try Right first, you still end up on the "1".
From the "1", possible moves are Down and Left:
If you try Down first, it returns true, which bubbles up the call stack - success!
If you try Left first, you end up on the "7", so recurse to the previous step.
And that's all that can ever happen. So using * for a return-false-backtrack, and ! for a success, any of the following are possible:
R-D!
R-L-D*-R-D!
R-L-R-L-R-L-R-L (keep going for a long, long time....) R-L-R-D!
So for a solvable maze, and a truly random generator, this will eventually solve the maze, although it could take a very long time. Something to note with this though, is it does not really backtrack that much: only ever a single step from a 2 or 0 node.
However, there's still the problem of the unsolveable maze, and I don't think that is possible given a totally ignorant rat. The reason for this is that for a brute force recursion like this, there are only two possible termination conditions:
The goal has been found.
All possible paths have been tried.
And with a totally ignorant rat, there is no way to detect the second!
Consider the following maze:
7 1 1 1
0 0 0 0
0 0 0 0
1 1 1 9
The totally ignorant rat will just wander left and right across the top row forever, and so the program will never terminate!
The solution to this is that the rat must be at least a bit intelligent, and remember where it has been (which will also make the solveable maze run quicker in most cases and backtrack along entire paths instead of only for single nodes). However, this answer is getting a bit too long already, so if you're interested in that I'll refer you to my other maze-solving answer here: Java Recursive Maze Solver problems
Oh, just two final points on Random:
You don't need to create a new Random each time - just create a
global one and call nextInt each time.
nextInt(n) returns between 0 (inclusive) and n (exclusive), so you
need nextInt(4) not nextInt(3).
Hope this all helps!
if you want to move in random, u need to know the states you've been already in them, so u will need a tree, otherwise u can keep the most left path when the rat is in multi way place.
now lets think of recursive + random. it can not be that hard. you can have a function that returns the list of points it has been in them, and get correct position as input, there is a bit of problem and the idiot rat can got back the way he already came from, so lets solve it with adding previous point as another input for our function.
every thing in place. now we wana know if the idiot rat runs into a dead path or an agent. how about making 2 exceptions for this situations and handling them in recursive function??
well, i don't think there will be any more problems on way. actually i'm temped to try it myselft. that would be fun :D
good luck with the idiot rat
I'd like to do some analysis of your algorithm design before proposing a solution.
You mention that you want to use a random walk algorithm. No problem with that it's a perfectly acceptable (though not necessarily efficient) way to look for a path. However you need to be aware that it has some implications.
In general random walk will not tell you when there is no solution. If you just keep trying paths at random you will never exhaust the search tree.
If this is unacceptable (i.e. it needs to be able to halt when there is no soltuion) then you need to keep a record of paths already attempted and randomise only those not yet attempted.
Random walk won't necessarily find the optimal solution unless there is only one solution. In other words if there are loops / multiple paths in your maze then there's no guarantee you are finding the fastest.
I can't actually see the difference between agents and obstacles in your problem. In both cases you need to backtrack and find another path. If there is a difference then you'll need to point it out.
So assuming your maze could have zero or more successful paths and you are not looking for the optimal path (in which case you really should use A* or similar), the structure of a solution should look something like:
public List<Position> findPath(Set<Position> closedSet, Position from, Position to) {
if (from.equals(to))
return List.of(to);
while (from.hasNeighboursNotIn(closedSet)) {
Position pos = from.getRandomNeighbourNotIn(closedSet);
closedSet.add(pos);
List<Position> path = findPath(closedSet, pos, to);
if (!path.isEmpty())
return List.of(pos, path);
}
closedSet.add(from);
return Collection.EMPTY_LIST;
}
This uses lots of pseudo-code (e.g. there is no List.of(item, list)) but you get the idea.