basic recursive backtracking (robot 2D pathfinding) - java

I'm working on a practice problem and is stuck. The problem asks to write a method that takes in two integers x and y to print all solutions for traveling in the 2D plane from (0,0) to (x,y) by repeatedly using one of three moves:
move right 1 (E)
move up 1 (N)
move right 1 and up 1 (NE)
These are some example calls:
call: travel(2, 1)
output: E E N // E N E // E NE // N E E // NE E
I wrote the following code:
public void travel(int x, int y) {
if (x == 0 && y == 0) {
System.out.println();
} else if (x > 0 && y > 0) {
System.out.print("E ");
travel(x-1, y);
System.out.print("N ");
travel(x, y-1);
System.out.print("NE ");
travel(x-1, y-1);
} else if (x > 0 && y == 0) {
System.out.print("E ");
travel(x-1, y);
} else if (y > 0 && x == 0) {
System.out.print("N ");
travel(x, y-1);
}
}
Calling the above method results in the following code:
call: travel(2,1);
output: E E N // N E // NE // N E E // NE E
I know that for this example call the problem lies with the E only getting printed once for three different cases that require E because the E is printed before the subsequent recursive methods are called.
I would like to fix this (without certainty that this is the right approach) by attaching the System.out.print command with each calling of the travel method. That way whenever travel method is called the result is printed with the first letter every time. However, since the method doesn't return anything, I can't insert the method within the print statement. This is where I've been stuck for a long time.
Any advice on how to go from here would be appreciated.

When recursively building solutions, it's common to pass a partially built solution as an argument to the recursive call.
public void travel(int x, int y, String path) {
if (x == 0 && y == 0) {
System.out.println(path);
} else if (x > 0 && y > 0) {
travel(x-1, y, path + ' E');
travel(x, y-1, path + ' N');
travel(x-1, y-1, path + ' NE');
} else if (x > 0 && y == 0) {
travel(x-1, y, path + ' E');
} else if (y > 0 && x == 0) {
travel(x, y-1, path + ' N');
}
}
See how we build the path as we go along - and let the function calls handle the complexity of remembering where we are in the search? This also has the nice property of simplifying our code, since we get exactly one call to System.out.println per path.

Related

Difficulty in writing a recursive solution to "Rat in a maze" problem

My question is essentially a doubt about recursion. I was solving the classic "Rat in a Maze" DFS traversal problem. My input was an n*n int array a[][] where for indices i and j, a[i][j] could either be 0 or 1. 0 meant the hypothetical rat couldn't visit the element and 1 meant it could. The rat could only go downwards("D") or rightwards("R"). The task was to output all movement Strings like RDRDRD that represented the rat's movement through the maze. The rat starts from a[0][0] and must reach a[n-1][n-1]. The input was the maze itself.
I wrote the following code
public boolean isSafe(int x, int y, int[][] a, int n)
{
if(x >= 0 && x < n && y >= 0 && y < n && a[x][y] == 1)
return true;
else
return false;
}
public ArrayList<String> printPath(int[][] a, int n)
{
ArrayList<String> res = new ArrayList<String>();
solve(0,0,new String(), res,a,n);
return res;
}
public void solve(int x, int y, String sol, ArrayList<String> res ,
int[][]a, int n)
{
if(x == n-1 && y == n-1)
{
res.add(sol);
return;
}
y++;
if(isSafe(x,y,a,n))
{
solve(x,y,sol + "R",res,a,n);
}
else
y--;
x++;
if(isSafe(x,y,a,n))
{
solve(x,y,sol+"D",res,a,n);
}
else
x--;
}`
where isSafe check whether a movement is permitted, printPath is a helper function for printing the output and solve is the recursive function used to traverse the maze.a represents the maze array as a 2-D array.
For the input
{1 0 0 0
1 1 0 1
0 1 0 0
0 1 1 1}
I get the following output
DRDDRR DDDRR
Obviously the second string represents an incorrect result.
However, when I changed the solve function like so
public void solve(int x, int y, String sol, ArrayList<String> res,
int[][]a, int n)
{
if(x == n-1 && y == n-1)
{
res.add(sol);
return;
}
if(!isSafe(x,y,a,n))
return;
solve(x+1,y,sol + "D",res,a,n);
solve(x,y+1,sol + "R",res,a,n);
return;
}
I get the correct output. What I am failing to understand is what resulted in the incorrect output in my previous solution, as to me the two solutions are logically similar.
I know it's a long read, but any insight would be greatly appreciated.
In the first solution the variable increment y++ is only undone if the call to isSafe with the incremented value comes back negative and is carried over to the check of x if it was true. This means that the down check on a field that has a valid neighbor to the right, in particular the field [1][0], will be performed with the incremented value of y instead of the correct one.
If you modify the first solution like this
y++;
if(isSafe(x,y,a,n)){
solve(x,y,sol + "R",res,a,n);
}
y--;
the first solution will work correctly as does the second one. In the second solution the increment is only done on the function argument, not a local variable.
A general advice is to not modify your input. And it is the case that your problem comes from just that. Here I modified your code so it doesn't do that. It's much more readable in my opinion and now you're sure of what x or y value you're using.:
if (isSafe(x, y + 1, a, n)) {
solve(x, y + 1, sol + "R", res, a, n);
}
if (isSafe(x + 1, y, a, n)) {
solve(x + 1, y, sol + "D", res, a, n);
}

Exception in thread "AWT-EventQueue-0" java.lang.ArithmeticException: / by zero in part of the program where it should divide numbers

I tried searching stackoverflow for answer but i could not find it. i figured out when i remove part of the program that divides numbers:
if(znak == 0) {
Resenje = x + y;
}else if(znak == 1) {
Resenje = x - y;
}else if(znak == 2) {
Resenje = x/y;
} else if(znak == 3) {
Resenje = x*y;
}else {
System.out.println("Greska u programu");
}
that error does not appear. i think the problem maybe if number is float but it is stored in int... Thank you, if you need any additional information im here to provide it.. :)
PS code is messy because i made it long time ago.. sorry, i cant figure out how to properly format it, i posted it on pastebin, i hope you dont mind it.. :)
https://pastebin.com/sfG9JEbR link for code
while(vece = true) {
// System.out.println(Odabir1);
x = random.nextInt(Odabir1);
// System.out.println(x);
y = random.nextInt(Odabir1);
// System.out.println(y);
//if(x == (int)x) {
if(x-y >= 0 && x+y <= Odabir1 && x+y!=0 && x-y!=0 && x/y >= 0 && x/y == (int)x && x*y >= 0 && x*y <= Odabir1) {
System.out.println(x + " " + y);
break;
}
}
when i try adding && y == 0; i get same error in every possibility

What is wrong with my Java recursive function?

I'm trying to write a relatively straightforward recursive program in Java to compute all the possible ways to traverse a 4x4 matrix (not necessarily traveling through every spot), starting at the top left and ending in the bottom right spaces. I use a 2-D array to do this, marking off visited spaces with "1"s as I go.
It's been a while since I've worked recursively and I can't seem to get the output I expect. The output from the code below is "2" - obviously, the result should be much higher. I know there's something tiny I'm overlooking. Can someone tell me what it is?
public static void main(String[] args) {
int[][] matrix = new int[4][4];
int result = moveRobot(matrix, 0, 0);
System.out.print(result + "");
}
public static int moveRobot(int[][] matrix, int x, int y) {
if (x == 3 && y == 3) {
return 1;
} else if (x < 0 || y < 0 || x > 3 || y > 3) {
return 0;
} else if (matrix[x][y] == 1) {
return 0;
} else {
matrix[x][y] = 1;
return moveRobot(matrix, x, y+1) + moveRobot(matrix, x+1, y) + moveRobot(matrix, x, y-1) +
moveRobot(matrix, x-1, y);
}
}
The problem is that the matrix is not copied but passed by value of the reference to it. Every time you modify it such in matrix[x][y] = 1 other successive code paths will see the modification instead that working on an unmodified state.
For example here:
moveRobot(matrix, x, y+1) + moveRobot(matrix, x+1, y)
Entering the first call will modify matrix, so in second moveRobot call you'd end up with 1 in matrix[x][y+1] while that's not what you want.

How to end my recursion

I need to program a method to solve a maze (2-dimensional array). I need to stay directly left of the wall at all times and my method should end when either I've reached the exit point (which is always at the same position) or when there is no solution possible (and, after running through the maze I'm back at the entry point).
I was able to do all that, no problems, I can visually ensure that it's doing what I want it to do (we've got some other methods from our instructor which output the visuals) and my console debug output is right as well.
This is the relevant code:
public static void main(String[] args) {
maze = generateMaze(10,10);
walk(1,0,0);
}
public static void walk(int x, int y, int direction) {
System.out.println("x = " + x + " y = " + y); //debug output
draw(x,y,maze); //draws current position
if (x == maze.length-1 && y == maze[1].length-2) { //terminate when reached exit
System.out.println("Geschafft!");
return;
}
if (x == 1 && y == 0 && direction == 3) { //terminate when at starting point again (no solution)
System.out.println("Keine Lösung möglich.");
return;
}
if (direction == 0) { //go down
if (maze [x][y+1]) {
walk(x,y,1);
}
walk(x,y+1,2);
}
if (direction == 1) { //go right
if(maze [x+1][y]) {
walk(x,y,3);
}
walk(x+1,y,0);
}
if (direction == 2) { //go left
if(maze [x-1][y]) {
walk(x,y,0);
}
walk(x-1,y,3);
}
if (direction == 3) { //go up
if(maze[x][y-1]) {
walk(x,y,2);
}
walk(x,y-1,1);
}
}
There's just one problem: how do I end my recursion correctly? This is what I get form the console:
x = 1 y = 0
x = 1 y = 1
x = 1 y = 1
x = 1 y = 2
and so on...
x = 8 y = 8
x = 9 y = 8
Geschafft!
x = 8 y = 9
x = 8 y = 9
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
at maze.MazeSolution.walk(MazeSolution.java:26)
at maze.MazeSolution.walk(MazeSolution.java:39)
and some more of that
I do understand the error, the recursion obviously doesn't end where I want it to and x or y are increased and try to use an index in the array that isn't there.
Why doesn't the recursion end with the return statement, when either of these situations come true:
if (x == maze.length-1 && y == maze[1].length-2) { //terminate when reached exit
System.out.println("Geschafft!");
return;
}
if (x == 1 && y == 0 && direction == 3) { //terminate when at starting point again (no solution)
System.out.println("Keine Lösung möglich.");
return;
}
What do I need to do to end it correctly?
I greatly appreciate your help, show some love for a beginner and tell me what to do.
Add to the beginning
public static void walk(int x, int y, int direction) {
System.out.println("x = " + x + " y = " + y); //debug output
if (x >= 10 || x < 0 || y >= 10 || y < 0) return;
Look at your returns and where you may return to. You can return in the middle of your enclosing function which has other calls to walk, without the guards to ensure they're not called.
I recommend re-implementing your logic; think about having if/else pairs to ensure mutual exclusion.
Why don't you simply return true or false and react on it?
So basically you add to your two end cases return true; for code ended.
if(walk(...)) return true;

Recursive Back tracking in a maze in java

Hi im new to the site so sorry if this is a repeat question but none of the previous questions seemed to match mine
I'm practising search algorithms within a maze structure and my attempt at a recursive backtracking is not working
Basically I have followed a exercise on a book Dietel volume 7 to create a maze and use recursion to find the solution but all my code does is:
finds the start position.
gets to the next position
then says there is no other move and exits the program
This is my method its know its bulky but im still working on it
public boolean mazeTraversal( char maze2[][], int x, int y)
{
lastX = x;
lastY = y;
maze[ x ][ y ] = 'x';
printMaze();
showPosition();
showMoves();
System.out.println("Press the key 'g' to traverse the maze : ");
move++;
if((x == Y_START) && (x == X_START) && (move > 1))
{
System.out.println("You have gone back to the start");
return false;
}
else if ( mazeExited( x, y ) && ( move > 1 ) )
{
System.out.println("You have reached the end");
return true;
}
else
{
char response = scanner.nextLine().charAt( 0 );
showPosition();
showMoves();
System.out.println( "Enter 'g' to continue, 'e' to exit: " );
if(response == 'e')
{
System.exit(0);
}
if(response == 'g')
while(checkMaze(x,y) == validMove(x,y) && checkMaze(x,y)!= mazeExited(x,y))
{
for(int count = 0; count < 4; count++)
{
switch (count)
{
case (DOWN):
if ( validMove( x + 1, y ) )
{
mazeTraversal(maze2, x + 1, y);
}
break;
case (RIGHT):
if ( validMove( x, y + 1 ) )
{
mazeTraversal( maze2, x, y + 1 );
}
break;
case (UP): // move up
if ( validMove( x - 1, y ) )
{
mazeTraversal( maze2, x - 1, y );
}
break;
case (LEFT): // move left
if ( validMove( x, y - 1 ) )
{
mazeTraversal( maze2, x, y - 1 );
}
}
}
}
}
return false;
}
Any pointers would be great.
Thanks Mike
I would consider returning your recursive calls to mazeTraversal() in your else block, instead of returning false.
A few things.
1) What is the purpose of maze2 ? You never use it or change it. Perhaps you should remove maze2 as a parameter and just update/reference maze[][] instead?
2) There is no exit condition. Even when one recursive call reaches the end and returns true, the success message will display and then the program will continue attempting to traverse the maze.
3) There are multiple things wrong with the while loop. For one, the condition will always evaluate as true. It does not look like you break or return out of the loop at all )but you have a few missing braces so I might be wrong).

Categories