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

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);
}

Related

Writing recursive method to compare even and odd digits within number

Basically, I am trying to write a method where a number is inputted and if there are more odd digits than even digits in the number, it returns "true", and else, false. I think I need to use tail recursion but I cannot figure it out.
public static boolean moreOddThanEven(int x) {
if (x == 0) {
return false;
}
if (x % 2 == 0) {
return moreOddThanEven(x / 10);
} else {
return moreOddThanEven(x / 10);
}
}
public static boolean moreOddThanEven2(int x) {
return moreOddThanEvenTR(x, 0, 0);
}
public static boolean moreOddThanEvenTR(int x, int odd, int even) {
if (x == 0) {
return false;
}
if (x%2==0) {
return moreOddThanEvenTR(x / 10, odd, even+1);
}
if (x%2!=0) {
return moreOddThanEvenTR(x / 10, odd+1, even);
}
if (odd <= even) {
return false;
} else {
return true;
}
}
I think using tail recursion is the right idea. Here is my attempt, assuming we can use more than one parameter in the recursive function:
public static boolean compareOddEven(int x, int count) {
//This is when we reach the end of the recursion (ones place).
if(x<10) {
//if odd, add 1, if even subtract 1
count += (x%2==1) ? 1 : -1;
return count>0;
}
else{
int digit = x;
//We use this loop in order to get the leftmost digit and read whether it is odd or even.
//Subsequently, we add or subtract 1 to the count based on the digit's parity and we pass this count into the next recursion in order to keep track.
while (digit > 9) {
digit /= 10;
}
count += (digit%2==1) ? 1 : -1;
//Get rid of the first digit to get next number to use in recursive call.
int removedFirstDigit = x % (int) Math.pow(10, (int) Math.log10(x));
//tail recursion
return compareOddEven(removedFirstDigit, count);
}
}
Explanation. We can accomplish this with just one method if we keep track of the count of odd and even digits the second parameter of the method. It will be less cumbersome to keep track of the count rather than keeping track of both counts of the odd and even numbers (and avoids the comparisons at the end which would not make it a tail recursion).
With this in mind, our approach is to start at the leftmost digit of the number we input and move to the right with each new recursive call. It is possible to start from right and go left in counting the parity of the digits as well.
So with every new recursive call, we pass in the count to the function as an argument. When we finally reach the ones digit, the nonnegativity of the count tells us whether there are more odd or even digits. To see this more clearly, I recommend printing out some of the arguments right before the recursive call is made.
Further note that when we reach the ones place, the truth value of count>0 will be propagated up the chain of recursive calls to give the final result that we desire.
Example call:
System.out.println(compareOddEven(21468233, 0));
Output:
false
There is a simple reason why you are stuck: you have to count the evens/odds like in 77778888888999. In fact you need to count the sum of (odds - evens), the oddity.
public static boolean moreOddThanEven(int x) {
assert x >= 0;
return x != 0 && oddity(x) > 0;
}
private static int oddity(int x) {
if (x == 0) {
return 0;
}
if (x % 2 == 0) {
return oddity(x / 10) - 1;
} else {
return oddity(x / 10) + 1;
}
}
Recursion is not needed (nor is more than one line):
public static boolean moreOddThanEven(int x) {
return (""+x).replaceAll("[02468]", "").length() > ((int) Math.log10(x)+1) / 2;
}
or the longer, but non-mathy version:
public static boolean moreOddThanEven(int x) {
return (""+x).replaceAll("[02468]", "").length() > ((int) (""+x).replaceAll("[13579]", "").length();
}
If you have an easier time thinking about loops than tail recursion, it's worth knowing that you can translate any loop into tail recursion (and vice versa, but that's different topic). First, we need to get the loop into this shape:
initialize a, b, ...
while (<some condition on a, b, ...>) {
Update a, b, ... using old values of a, b, ...
}
return <any function of a, b ...>
it translates to:
TypeOfReturn while_loop(TypeOfA a, TypeOfB b, ...) {
if (!(<some condition on a, b, ...>)) {
return <any function of a, b, c ...>;
}
Update a, b, ... using old values of a, b, ...
return while_loop(a, b, ...);
}
Let's apply this to your problem. As a loop:
// x is the input
int oddMinusEven = 0;
while (x) {
oddMinusEven += 2 * (x % 2) - 1;
x /= 10;
}
return oddMinusEven > 0;
We get:
bool hasMoreOddThanEvenDigits(int x, int oddMinusEven) {
if (!x) return oddMinusEven > 0;
oddMinusEven += 2 * (x % 2) - 1;
x /= 10;
return hasMoreOddThanEvenDigits(x, oddMinusEven);
}
We can clean this up a bit to make it less verbose:
int hasMoreOddThanEvenDigits(int x, int oddMinusEven) {
return x ? hasMoreOddThanEvenDigits(x / 10, oddMinusEven + 2 * (x % 2) - 1) : oddMinusEven > 0;
}
We run the loop with a "top level" function call that initializes variables:
return getMoreOddThanEvenDigits(x, 0) > 0;
It's fun to see what a good compiler does with the two codes. As you'd expect, they lead to nearly identical machine code. If we can do a rule-based transformation, so can the compiler.

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.

RandomWalk solution issue

PROBLEM
I am working on a code where I am simulating a dog walking in a city - trying to escape the city. The dog makes random choices of which way to go to at each intersection with equal probability.If stuck at a dead end the dog will come directly back to the middle of a big city and start all over again. The dog will do this again and again until it gets out of the city or until it gets tired after T number of trials. But by the time the the dog starts again from the middle(N/2,N/2) on each try, it will have forgotten all the intersections it had visited in the previous attempt.
IDEA
The idea is to mimic a code given in our textbook and come up with the solution. We were given input N, T - where N is the number of north-south and east-west streets in the city and T is the number of times the dog will try to get out of the city before it gives up. We have to draw it out, using StdDraw. We have been given how to make random movements - generate a number between 0 and 4 - up: 0 right: 1 down: 2 left: 3
My Approach
import java.util.Random;
public class RandomWalk {
private static final Random RNG = new Random (Long.getLong ("seed",
System.nanoTime()));
public static void main(String[] args) {
int N = Integer.parseInt(args[0]); // lattice size
int T = Integer.parseInt(args[1]); // number of trials
int deadEnds = 0; // trials resulting in a dead end
StdDraw.setCanvasSize();
StdDraw.setXscale(0,N);
StdDraw.setYscale(0,N);
// simulate T self-avoiding walks
for (int t = 0; t < T; t++) {
StdDraw.clear();
StdDraw.setPenRadius(0.002);
StdDraw.setPenColor(StdDraw.LIGHT_GRAY);
for(int i=0;i<N;i++){
StdDraw.line(i, 0, i, N);
StdDraw.line(0, i, N, i);
}
StdDraw.setPenColor(StdDraw.RED);
StdDraw.setPenRadius(0.01);
boolean[][] a = new boolean[N][N]; // intersections visited
int x = N/2, y = N/2; // current position
// repeatedly take a random step, unless you've already escaped
while (x > 0 && x < N-1 && y > 0 && y < N-1) {
int t_x = x;
int t_y=y;
// dead-end, so break out of loop
if (a[x-1][y] && a[x+1][y] && a[x][y-1] && a[x][y+1]) {
deadEnds++;
break;
}
// mark (x, y) as visited
a[x][y] = true;
// take a random step to unvisited neighbor
int r = RNG.nextInt(4);
if (r ==3) {
//move left
if (!a[x-1][y])
t_x--;
}
else if (r == 1 ) {
//move right
if (!a[x+1][y])
t_x++;
}
else if (r == 2) {
//move down
if (!a[x][y-1])
t_y--;
}
else if (r == 0) {
//move up
if (!a[x][y+1])
t_y++;
}
StdDraw.line(t_x, t_y, x, y);
x = t_x;
y = t_y;
}
System.out.println("T: "+t);
}
System.out.println(100*deadEnds/T + "% dead ends");
}
}
ISSUE
Given N - 15, T - 10, -Dseed=5463786 we should get an output like - http://postimg.org/image/s5iekbkpf/
I am getting - see http://postimg.org/image/nxipit0pp/
I don't know where I am going wrong. I know this is very specific in nature, but I am really confused so as to what I am doing wrong. I tried all 24 permutations of 0,1,2,3 but none of them gave the output desired. So, I conclude that the issue in in my code.
check your StdDraw.java with:
http://introcs.cs.princeton.edu/java/stdlib/StdDraw.java.html
your code should be fine, I got the expected result

Mathematical induction of this Code?

I don't really understand how I use proof by induction on this Code.
I just wanna know how to prove the correctness of this code and algorithm.
Prove that we will never count items which already counted .
Algorithm for countCells(x,y)
if the cell at(x,y) is outside
the grid the result is 0;
else if
the color of the cell at (x, y) is not the abnormal color the result is 0;
else
set the color of the cell at (x, y) to a temporary
color; the result is 1 plus the number of cells in each piece of the
blob that includes a nearest neighbor;
public int countCells(int x, int y)
{
int result;
if(x<0 || x>=N || y<0 || y>=N) // N is the maximum value of the matrix
return 0;
else if(!getColor(x,y).equals(ABNORMAL)) //
return 0;
else
{
recolor(x, y, TEMPORARY);
return 1 + countCells(x-1, y+1) + countCells(x, y+1)
+ countCells(x+1, y+1) + countCells(x-1, y)
+ countCells(x+1, y) + countCells(x-1, y-1)
+ countCells(x, y-1) + countCells(x+1, y-1)
}
}
the following link show how this works
http://kin.naver.com/qna/detail.nhn?d1id=1&dirId=104&docId=186514818
Proof by induction
Prove for base case condition (n = 1)
Prove for all assumption step ( n = k )
Prove for inductive step + 1 (n = k + 1)
So call your function with a base for step 1, let k equal some other generic input, then do the input + 1.
Basically you want to test the edge cases of your functions to ensure that they work properly. Your teacher probably wants you to just write test conditions for the function above.

Recursive method - Java

Addition information:
Chip doesn't support multiplication, only addition. I should work around this problem by creating a recursive method, mult(), that performs multiplication
of x and y by adding x to itself y times. Its arguments are x and y and its return
value is the product of x and y. I should then write the method and a main() to
call it.
It's pure logical thinking, but I get lost every time I try to think what to do.
I am stuck at the math part..
What I have, that doesn't work and I know the math is wrong, but I am not good at this:
public static void mult(int x, int y) {
x = 0;
y = 0;
if (y > 0) {
for (int i = 0; i < y; i++) {
x = x * (x * y);
return mult(x, y);
}
}
}
When I hear "recursion", I expect to see two things:
A function calling itself with modified arguments each time.
A stopping condition right at the top that tells the function when to stop, avoiding an infinite stack.
So where are yours? Start with writing those down in words before you write code.
One possibility is to use an accumulator which will store the current value of the multiplication. I replace missing statements by ??? :
public static void main(String []args){
System.out.println(mult(2,5));
}
public static int mult(int x, int y) {
if(???) return ???;
else return multAcc(???,???,???);
}
private static int multAcc(int x, int y, int acc){
if(???) return ???;
else return multAcc(???, ???, ???);
}
... by adding x to itself y times.
You could actually do that, instead of multiplying. Oh, and maybe if you don't set both x and y to zero, you would have something to add ;-)
One last thing: If you want a recursive solution, you don't need the for-loop.
Java has no TCO by design, so using recursion for linear (not tree-like) processes is very bad idea. Especially for such task, which will most likely become a bottleneck in your program. Use loop instead.
Oh, it must be recursive anyway? Looks like a homework task. Do it yourself then.
All you need to remember is that a multiplication is a repeated addition (assuming that both operands are >= 0), so we have:
The base case is when y is zero
If y is not zero, then add x one more time, and subtract 1 from y
Notice that as long as y is positive, it'll eventually have a value of zero. So basically we keep adding x a total number of y times; this is what I mean:
public static int mult(int x, int y) {
if (y == 0)
return 0;
return x + mult(x, y-1);
}
The same code can be written in a tail-recursive style, too - meaning: there's nothing to do after the recursive call returns, and this is important for certain languages that support a so-called tail-call optimization:
public static int mult(int x, int y, int accumulator) {
if (y == 0)
return accumulator;
return mult(x, y-1, x + accumulator);
}
The above will get called as follows, noticing that the last parameter is always initialized in zero:
mult(10, 5, 0)
=> 50
public static int mult(int x, int y) {
if (y == 0) {
return 0;
}
if (y > 0) {
return x + mult(x, y - 1);
} else {
return -x + mult(x, y + 1);
}
}
this was the solution by the way

Categories