I need to write a method that checks how many possible ways there are to finish a grid (a 2D array).
the movement inside the grid is like this:
start with [0][0] take the number inside there (for instance 14) then go to either
[array.[0][0]%10][array.[0][0]/10] or [array.[0][0]/10][array.[0][0]%10]
for our example:
[1][4] or [4][1]
until you get to the end of the array (bottom right corner).
I can get to the end of the array (all possible ways) - my problem is to count how many times I actually finished the array - I can not use a variable outside of the method, and the method has to be recursive.
this is the code :
private static int howMany(int[][] array, int y, int x, int count) {
if(y+(array[y][x]%10) < array.length && x+(array[y][x]/10)< array[y].length && array[y][x]!=0) {
System.out.println("["+y+"]["+x+"] is: "+array[y][x]);
howMany(array, y+(array[y][x]%10), x+(array[y][x]/10),count);
}
if(y+(array[y][x]/10) < array.length && x+(array[y][x]%10)< array[y].length && array[y][x]!=0) {
System.out.println("["+y+"]["+x+"] is: "+array[y][x]);
howMany(array, y+(array[y][x]/10), x+(array[y][x]%10),count);
}
if(y==array.length-1 && x==array[y].length-1) count++;
return count;
}
this is obviously wrong and will return what count was in the first place, I tried many other ways but to no avail...
here's the full class (with an array to test):
link to full class
edit: a big Thanks to everyone for their help!
The count is already returned from each call to howMany. I think you just need to save it:
count = howMany(array, y + (array[y][x] % 10), x + (array[y][x] / 10), count);
Do this inside both if blocks. I made this change in your linked code and got the expected result (3).
You are already on the right track, since your method signature returns an int. You should define a variable to hold the count, increment it for the primary recursive call, and add to it the result of the recursive method itself. Passing the count into the each recursive call is unnecessary and should be removed.
Return 1 if you've reached the end of the array (bottom right corner) and 1+howMany(array, newY, newX) otherwise. You don't need to keep the count and pass it every time. The function will work so:
1 + returned value of 2nd call =
1 + 1 + returned value of 3rd call =
1 + 1 + 1 + returned value of 4th call =... and so on.
Finally as result you'll get number of calls which is what you want.
Related
I'm trying to solve the problem of "count ways to reach the nth step in a staircase" with recursion. When given a number of stairs to climb, I have to calculate the number of ways to climb taking either 1 or 2 steps at a time. For example, if there are 4 stairs, we would return 5 since we would have:
* 1 1 1 1
* 1 1 2
* 1 2 1
* 2 1 1
* 2 2
My code is currently throwing a stack overflow exception:
public static int countWaysToClimb(int stairs) {
return countWaysToClimbHelper(stairs, 0, 0);
}
public static int countWaysToClimbHelper(int sumNeeded, int currentSum, int possibleCombos) {
// base - we will reach this base multiple times
if (sumNeeded == currentSum) {
possibleCombos++;
// if we already found a combo, we need to reset the sum
countWaysToClimbHelper(sumNeeded,0,possibleCombos);
}
else if (currentSum > sumNeeded) {
return 0;
}
// recurse - add 1 and then add 2
countWaysToClimbHelper(sumNeeded,currentSum+1,possibleCombos);
countWaysToClimbHelper(sumNeeded,currentSum+2,possibleCombos);
return possibleCombos;
}
Thank you!
There are some issues in your code:
Base case (condition that terminates the recursion) is incorrect. Every branch of recursive calls spawn new branches when it hits the condition if (sumNeeded == currentSum) is meat instead of returning the number of combinations. You created an infinite recursion that inevitably leads to a StackOverflowError. You have to place a return statement inside the curly braces after the first if in your code. And comment out the first recursive call (with 0 sum passed as an argument) you'll face the second problem: for any input, your code will yield 0.
Results returned by recursive calls of your method countWaysToClimbHelper() are omitted. Variable possibleCombos isn't affected by these calls. Each method call allocates its own copy of this variable possibleCombos on the stack (a memory aria where JVM stores data for each method call), and their values are not related anyhow.
you actually don't need to pass the number of combinations as a parameter, instead you have to return it.
Before moving further, let me recap the basics of recursion.
Every recursive method should contain two parts:
base case - that represents a simple edge-case for which the outcome is known in advance. For this problem, there are two edge-cases:
sumNeeded == currentSum - the return value is 1, i.e. one combination was found;
sumNeeded > currentSum - the return value is 0.
recursive case - a part of a solution where recursive calls a made and when the main logic resides. In your recursive case you need to accumulate the value of the number of combination, which will be the sum of values returned be two branches of execution: take 1 step or 2 steps.
So the fixed code might look like that:
public static int countWaysToClimb(int stairs) {
return countWaysToClimbHelper(stairs, 0);
}
public static int countWaysToClimbHelper(int sumNeeded, int currentSum) {
// base - we will reach this base multiple times
if (sumNeeded == currentSum) {
return 1;
} else if (currentSum > sumNeeded) {
return 0;
}
// recurse - add 1 and then add 2
int possibleCombos = 0;
possibleCombos += countWaysToClimbHelper(sumNeeded,currentSum + 1);
possibleCombos += countWaysToClimbHelper(sumNeeded,currentSum + 2);
return possibleCombos;
}
Note:
This code could be enhanced further. The whole logic can be implemented inside the countWaysToClimb() without using a helper-method. For that, instead of tracking the currentSum you need to subtract the number of steps from the sumNeeded when the method is called recursively.
Question:
How many calls are needed to recursively calculate the 7th Fibonacci value?
So this was a problem given to me and the answer was given to me as 41. Then I went to a professor because I didn't understand it, but I was given another answer. I think it was 25? (don't quote me on that) Then I went to another professor... and he told me the person who gave you this problem should have given you the sample code because there can be multiple ways to write this recursive function which would result in different amounts of calls.
So if this is true can you guys find different recursive functions that would result in a different amount of calls needed to get the 7th value of the sequence?
One way:
static long fibonacciR(int i)
{
if (i <= 1)
return i;
return fibonacciR(i - 1) + fibonacciR(i - 2);
}
Another way:
static final int f[] = {0,1,1,2,3,5,8,13,21,34,55,89,144};
static long fibonacciR2(int i)
{
if (i < f.length)
return f[i];
return fibonacciR2(i-1)+fibonacciR2(i-2);
}
In fact 'another' way is any number of other ways, depending on how big you make the table. When the table has two elements both methods are equal. When it has three there are 25 calls. When 4, 15. And so on.
Yet another way, to get specifically 25 calls:
static long fibonacciR3(int i)
{
if (i == 0)
return 0;
if (i <= 2)
return 1;
return fibonacciR(i - 1) + fibonacciR(i - 2);
}
I'm relatively new to Java programming and I've just started learning recursion, but I can't seem to figure out how this method works in my head.
private static int mystery(int w) {
{
if (w < 0) return 0;
int x = mystery (w-2);
return w - x;
}
}
Whenever a variable like 100 is put in, it outputs 50. When 200 is input, it outputs 100. When 2 is input, it outputs 2. When 25 is input, 13 is output. I'm not sure how this method works, and I'm trying to wrap my head around it.
The way I currently view it, if you put in 100, it'll bypass the first return statement since it is greater than 0.
when it gets to the second line, it'll do 100-2, which brings in 98, then goes to the third line and does 100 - 98 = 2. Which is then returned to the original call.
I know I'm messing up on the second line of the method where the mystery (w-2) is. I assume it would bring back the result of w-2 to the beginning of the method again, and it would continue to do the method over and over again until w is smaller than 0, which should output 0 again regardless of the answer. But that's not what happens, and I don't know why.
Can anyone explain what is going on here?
What you are missing is that on the second line it doesn't just do w - 2, but calls itself with w - 2. It doesn't go further until the call returns. And the second call calls itself if w isn't < 0 and so on until you reach value lower than 0 and then return. The execution will go like this, if you visualize it:
mystery(10)
> skip first line
> x = mystery(8)
> skip first line
> x = mystery(6)
> skip first line
> x = mystery(4)
> skip first line
> x = mystery(2)
> skip first line
> x = mystery(0)
> skip first line
> x = mystery(-2)
> return 0
> return 0 - 0 (0)
> return 2 - 0 (2)
> return 4 - 2 (2)
> return 6 - 2 (4)
> return 8 - 4 (4)
> return 10 - 4 (6)
With example of w = 10. I hope you understand it better now.
private static int mystery(int w) {
{
if (w < 0) return 0;
int x = mystery (w-2);
return w - x;
}
}
Let's imagine that we call mystery(3). What happens? w<0) is false, so we don't return 0. In the next line, we call some function called mystery using the value 3-2=1 as its argument.
Despite the fact that this function we've called happens to be the same one we've just called, it's still an ordinary function call, and it returns a value. It does this by calling the function called mystery, this time using the value -1 as the argument. And this time w<0 is true, so we just return 0. Now we're back in the second call to mystery, and we've set x = 0. So that call returns w - 0 = 1. That puts us back in the first call, and now x = 1, so we return w-x = 3-1 = 2.
You might want to take a few minutes and work through this using w=4 and see what you get - this will help you understand how the recursive calls work.
After you've done this, I suggest you add a print statement or two in the function to tell you where you are and what's happening, and that'll also help - but do it on paper first.
The two given answers are excellent. Both focus on the way how to get a grasp of what recursion is. The problem with recursion is, that it is so unnatural to one who do not know what recursion is, or do not know someone who does. It's like a snake eating itself again and again.
The best way to understand recursion is to write down the calls to a recursive method, by noying the current state when it's called, and after the call write the result back. You stack up the calls and that's also the way to not used recursion at all.
So do not try too hard to understand recursion at first but first focus on the program flow. If you have seen enough recursions, it will come to you.
I'm studying for my computer science final and am going back over some of the things that I never quite grasped when we went over them in class. The main thing being recursion. I think I've got the hang of the simple recursion example but am trying to work through one that was on a previous exam and am having trouble figuring out how it should be done.
Here is the question:
Texas numbers (Tx(n)) are defined as follows for non-negative numbers (assume true):
Tx(n) = 10 if n is 0
Tx(n) = 5 if n is 1
Tx(n) = 2*(Tx(n-1) + Tx(n-2) if n >= 2
We are then to write the recursion function for Texas numbers, after making some corrections after the test, here's what I've come up with, I think it's right, but not 100% sure.
public int Tx(int n) {
if(n == 0)
return 10;
else if (n == 1)
return 5;
else
return 2*(Tx(n-1) + Tx(n-2));
}
Then we are asked to computer the value of Tx(5). This is where I'm stuck. If the return statement for the else was simply n-1, I think I'd be able to figure it out, but the n-1 + n-2 is completely throwing me off.
Can anyone explain how this would work, or share some links that have similar examples. I have tried looking this up online and in my textbook but the examples I've found are either so advanced that I have no clue what's going on, or they only deal with something like return n-1, which I already know how to do.
Let's start with Tx(2). n > 1, so we have 2*(Tx(n-1) + Tx(n-2)) which is 2*(Tx(1) + Tx(0)).
But we already know Tx(1) and Tx(0)! So just substitute them in and you get 2*(5 + 10) -> 30. Great, so now we know T(2).
What about T(3)? 2*(Tx(2) + Tx(1)). Nice, we already know these too :) Again, just fill them in to get 2*(30 + 5) -> 70.
You can work forwards to get to Tx(5).
Your code is logically correct, you should just be using == to test equality, a single = is for assignment.
When you run your method, it will work backwards and solve smaller and smaller subproblems until it gets to a point where the answer is known, these are your base cases.
Tx(3)
2* Tx(2) + Tx(1)
2*Tx(1) + Tx(0) (5)
(5) (10)
In order for recursion to work, whatever you are doing each time to break the problem down into smaller problems needs to make some progress towards the base case. If it doesn't, you will just infinitely recurse until your computer runs out of space to store all of the repeated calls to the same function.
public int Tx(int n) {
if(n == 0)
return 10;
else
return Tx(n+1); // n will never reach 0!
}
Tx(1) becomes Tx(2) -> Tx(3) -> Tx(4) -> Tx(5) etc.
Your implementation is good, only one minor mistake - in the conditions you should replace = with == - it's not an assignment - it's a comparison.
By the way, what would you expect your method to return for Tx(-1) ?
You have implemented it right just change = with ==.
If you want to further reduce the time complexity you can store the result in an array global to the function so that your function doesnot compute results again and again for a same number this will only save you some time for large computations.
You can use something like this.
public int tx(int n , int []arr) {
if (arr[n] == 0) {
if (n == 1) {
arr[n] = 10;
}
else if (n == 2) {
arr[n] = 5;
}
else {
arr[n] = 2 * (tx((n - 1), arr) + tx((n - 2), arr));
}
}
return arr[n];
}
See whenever you ask the computer for the value Tx(5) it will call the recursive function and so the program will execute the else part because value of n=5.
Now in the else part 2*(Tx(n-1)+Tx(n-2)) will be executed.
In first iteration it will become 2*((2*(Tx(3)+Tx(2)))+(2*(Tx(2)+Tx(1)))) . The iteration will be continued until the value of n become 0 or 1.
I am trying to learn recursion in Java and have an array that takes in continuous input until the Scanner reads in a 0.
From there I have a method that (attempts) to calculate the number of positive integers in the array using recursion. This is the first recursive function I have ever written and I keep getting a stackoverflow error.
I have read tutorials and I still can't wrap my head around the basic understanding of recursion.
public class reuncF {
private static int start = 0;
private static int end = 98;
public static void main(String[] args) {
input = input.nextDouble();
list[i] = numInput;
computeSumPositive(numList, count);
}
}
return positives += solve(numbers, count++);
}
}
You forgot to stop your recursion!
There has to be some case where computeSumPositive returns without calling itself again. Otherwise it'll just keep going forever, never getting back to you.
If you did it with a loop, the loop would look like this:
int positives = 0;
for (int i = 0; i < numList.length; ++i) {
if (numList[i] > 0) {
positives++;
}
}
To do that recursively, you just find out what are the variables used in the loop. They are i, numList and positives.
computeSumPositive(int i, double[] numList, int positives)
Then we take a look at what the loop does. First, it checks whether we went too far,
so our recursive function should do that too. It'll have to return instead of just falling through like the loop does. And obviously, it must return the result:
{
if (! (i < numList.length))
return positives;
The loop then does the test and maybe increments positives, so the recursive function should also do that:
if (numList[i] > 0) {
positives++;
}
At the end of the loop, i is updated:
i++;
The loop just starts over, but the recursive function will have to call itself. Of course, we want it to use the new value of i and positives, but fortunately we updated those, so now we can just do:
return computeSumPositives (i, numList, positives);
}
The tricky bit is that the values i, numList, and are local to each call. Each invocation of computeSumPositives can see only the arguments it were given. If it changes them, none of the other invocation can see that change.
EDIT: So if we, for reasons we can only speculate about, wanted desperately for computeSumPositive to take only 2 parameters, we would have to "split up" positives across each invocation. Each invocation knows whether or not its number was positive or not; all we have to do is add them. Then it looks like this:
computeSumPositive(int i, double[] numList)
{
if (! (i < numList.length))
return 0; // I didn't find any at index i
if (numList[i] > 0) {
// Theres one I found + however many my later
// invocations will find.
return 1 + computeSumPositive (i+1, numList);
} else {
// I didn't find any, but my later invocations might.
return computeSumPositive (i+1, numList);
}
}
I find it helpful, when dealing with recursion, to figure out the termination case first.
It looks like you are treating 'count' as an index. So you could check if your at the last index in the array, if so and if the value is positive return a 1, if the value is non-positive return a 0 - dont recurse anymore.
If your not at the last index, and the value is positive return a 1 + the recursive function call, or if the value is non-positive just continue to recurse.
This will still cause a stack overflow for large arrays.
The value of count++ is the same as the value of count; the program uses the value and then increments it. But the result is that computeSumPositive keeps calling itself with the same value of count, which leads to infinite recursion. Note that each time computeSumPositive calls another computeSumPositive, each call has its own copy of the parameters (like count) and the local variables; so incrementing one computeSumPositive's copy of count has no effect on the value of count used by other recursive calls.
Change count++ to count + 1, and also add a way to halt the recursion. (At some point, you will be calling computeSumPositive to look at zero integers, and at that point, it should just return 0 and not call itself. You need to think about: how do you test whether you've reached that point?)