I have a simple java program that takes a number and executes a function based on that number.
public class Palidrome {
public static void main (String[] args) {
int N = 3;
System.out.println(palidrome(N));
}
public static String palidrome(int i) {
if (i == 0) return "S";
if (i == 1) return "T";
return palidrome(i-2)
+ palidrome(i-1)
+ palidrome(i-2);
}
}
So for this example N = 3, and the output is "TSTST". If N is changed to 5, the output is "TSTSTSTSTSTSTSTSTSTST" etc.
I'm struggling to figure out why this is the case. If N = 5, palidrome(i-1) and palidrome(i-2) will never reach (i == 0) or (i == 1) so nothing should be returned theoretically?
Thanks in advance!
This can be understood by drawing the recursion tree.
palindrome(5)
/ | \
palindrome(3) palindrome(4) palindrome(3)
/ | \ ............................
/ | \
palindrome(1) palindrome(2) palindrome(1)
/ | \
/ | \
palindrome(0) palindrome(1) palindrome(0)
So palindrome(5) will ultimately reach palindrome(0) and palindrome(1) calls.
NOTE: The recursion ends at palindrome(0) and palindrome(1) calls.
Let's run through what happens line by line for N = 5.
palindrome(5) is called
--> i is not 0 or 1
--> return the results of palindrome(3) + palindrome(4) + palindrome(3)
We need the results of palindrome(3) to build our result for palindrome(5). So palindrome(3) is called.
--> i is not 0 or 1
--> return the results of palindrome(1) + palindrome(2) + palindrome(1)
We need the results of palindrome(1) to build our result for palindrome(3). So palindrome(1) is called.
--> i = 1, so "T" is returned
We need the results of palindrome(2) to build our result for palindrome(3). So palindrome(2) is called.
--> i is not 0 or 1
--> return the results of palindrome(0) + palindrome(1) + palindrome(0)
I'll glaze over the recursion here, but we get "STS" for the results for palindrome(2).
This means we get palindrome(1) + palindrome(2) + palindrome(1) = "TSTST" for palindrome(3).
This result is returned to our original palindrome(5) call.
Hopefully that helps illustrate the recursion for you.
Each successive recursive call for palidrome should bring you closer to the base-case which is here:
if (i == 0) return "S";
if (i == 1) return "T";
so theoritcally saying
palidrome(i-1) and palidrome(i-2) will never reach (i == 0) or (i ==
1)
is wrong as those statements will be eventually reached but after the i changes to satisfy the condition.
How would var i change you are probably wondering! well through this statement:
return palidrome(i-2)
+ palidrome(i-1)
+ palidrome(i-2);
Here you are calling palidrome recursively but (i is decreased), this will eventually lead you to the base-case.
if your function never hit the base-case then you'll have an infinite recursion and this is not the case over here.
To simplify things lets take a look at this Example:
assume that you have a generous neighbor that will give you one apple if you visit him once, also another one if you visit him twice then he'll start giving you as mush as he gave you that last 2 times (that's actually a fibonacci sequence) so the general-case here is:
numberOfApplesThatYouGet= numberOfApplesThatYou'veGotIn(currentVisitNumber-1(Which is Last Visit))+numberOfApplesThatYou'veGotIn(currentVisitNumber-2)
and lets assume that
currentVisitNumber = n and numberOfApplesThatYouGet = a method called fib
so general rule would be -->
fib(n)=fib(n-1)+fib(n-2)
But we still need a base-case to terminate an infinite recursion and here the base-case is your first visit condition which is
if(n==0) return 0;//if you didn't visit him you'll get nothing
if(n==1) return 1;//if you did you'll get an apple
so the Method will look like this:
public int fib(int n) {
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
lets assume that you bare him three visits, how many apples would you get?
fib(3)->fib(2)+fib(1)
fib(2)->fib(1)+fib(0)->1+0->1
fib(1)->1
1+1=2
#done
Also take a look at this to form a better understanding of recursion.
Related
I'm still wrapping my mind around recursion, and I think I get basic ones like factorial. But I'd like further clarification when the return statement is a little more complex like on the following snippet:
/**
* #param n >= 0
* #return the nth Fibonacci number
*/
public static int fibonacci(int n) {
if (n == 0 || n == 1) {
return 1; // base cases
} else {
return fibonacci(n-1) + fibonacci(n-2); // recursive step
}
}
In the return statement, does the fibonacci(n-1) completely recur through, before going down the fibonacci(n-2) step (does that make sense)? If so, this seems very difficult to envision.
Yes, one invocation will recurse all the way down and return, before the other one starts executing.
The order of invocation in Java is well-defined: fibonacci(n-1) goes before fibonacci(n-2).
Edit: Since the question originally included [C++] tag, here is the C++ part of the story: one of the two invocations still has to complete before the other one starts to run, but which one, fibonacci(n-1) or fibonacci(n-2), is unspecified.
Since the function has no side effects, it does not matter which of the two invocations gets to run first. The only thing that is important for understanding of recursion is that both invocations must complete, and their results must be added together, before the invocation at the current level returns.
It isn't much more different than calling a different function than itself. It needs to finish before the calling function can do anything with the result.
finobacci(0); // ==> 1 (since n is zero, the base case is to return 1)
fibonacci(1); // ==> 1 (since n is one, the base case is to return 1)
Now lets try 2 which is not the base case:
fibonacci(2); // == (since it's not the base case)
fibonacci(1) + fibonacci(0); // == (both calls to fibonacci we already haver done above)
1 + 1 // ==> 2
So in reality what happens is that the call to fibonacci2 waits while each of the two recursive calls to finish, just like a function that does System.out.println would wait until it had printed the argument before continuing to the next line. Recursion isn't that special.
Trivia: This is the original series from Fibonacci himself. Modern mathematicians start the series with n as the base case result making the series 0, 1, 1, 2, ... rather than 1, 1, 2, 3, ....
it works in this way:
Fibonacci program:
public int fibonacci(int n) {
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
Explanation:
In fibonacci sequence each item is the sum of the previous two. So, as per recursive algorithm.
So,
fibonacci(5) = fibonacci(4) + fibonacci(3)
fibonacci(3) = fibonacci(2) + fibonacci(1)
fibonacci(4) = fibonacci(3) + fibonacci(2)
fibonacci(2) = fibonacci(1) + fibonacci(0)
Now you already know fibonacci(1)==1 and fibonacci(0) == 0. So, you can subsequently calculate the other values.
Now,
fibonacci(2) = 1+0 = 1
fibonacci(3) = 1+1 = 2
fibonacci(4) = 2+1 = 3
fibonacci(5) = 3+2 = 5
In multiple recursion the program calls itself with its first call until the base case is reached, in this case fibonacci(n-1); after that the recursion stops and return his value to continue calling the value to the second part of the recursion fibonacci(n-2).
If you don't visualize the multiple recursion in the program, this
fibonacci recursion tree may be helpful.
I am going through some simple recursion exercises in Java in order to understand the concept (which I struggle with). For all my study up to this point, I have relied heavily on Eclipse's debugger in order to understand exactly what my code is doing. However, when it comes to recursion, I find this not to be the case, because it is difficult to track exactly what is happening.
Considering the following code, a method that returns the nth Fibonacci number:
public int fibonacci(int n) {
if (n == 0 || n == 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
When using the debugger for this code, it's pretty difficult to track exactly what is happening and where/when. With only one variable, it changes every step, and, with a small n value, such as 7, it is already becoming difficult to track, due to the fact that there are so many steps that are executed before 13 is eventually reached.
I would like to know:
How can I debug my recursion code (in general) in a better way, in order to better understand recursion?
Am I focussing too much on debugging for this sort of thing, considering the concept return fibonacci(n - 1) + fibonacci(n - 2) is simple to understand?
How can I debug my recursion code?
First, make sure you have switched to the Debug perspective and you're seeing the correct windows (Variables, Expressions, Debug and your source code) e.g. like this:
Next, note that in Debug you can see how often the method is currently called. This list will grow and shrink depending on how many methods were called and have not returned yet.
You can click on one of the methods to change the scope. See how the contents of Variables changes when you change the scope.
Finally, to check arbitrary things, enter expressions in the Expressions window. This is almost like live coding. You can inspect virtually anything.
Am I focussing too much on debugging?
No. Learn doing it right and it will save you much time later.
Adding a System.out.println() needs to recompile and you need to reproduce the situation which is not always that simple.
You can debug it using a simple System.out.prinln() in each instruction where you print n value and its fibonnacci value.
Here's an example code:
public int fibonacci(int n) {
if (n == 0 || n == 1) {
System.out.println("your value is: " +n+ " and its Fibonacci value is: "+n);
return n;
} else {
System.out.println("your value is: " +n+ " and its Fibonacci value is: "+fibonacci(n - 1) + fibonacci(n - 2));
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
You can test the DEMO here.
"Inline" code makes it more difficult to use the Eclipse debugger because it has a strong focus on showing local variables which are not present. You can make this easier to step through by making things more verbose and saving to variables. This way you can more easily see what is happening and what results are. For example, modifying your code as follows will make it easier to use the debugger on:
public int fibonacci(int n) {
if (n == 0 || n == 1) {
return n;
} else {
int nMinus1 = fibonacci(n - 1);
int nMinus2 = fibonacci(n - 2);
int retValue = nMinus1 + nMinus2;
return retValue;
}
}
DISCLAIMER: I have not attempted to compile this code.
It took me a while to grasp recursion and, for one reason or another, I never found the debuggers useful. I'll try to explain you how I do and it doesn't involve the debugger (disclaimer: this is a personal method and it might by incorrect or not general).
In recursive code you always have at least a termination block and a
recursion block. Isolate mentally these 2 sections.
return n; -> termination block
return fibonacci(n - 1) + fibonacci(n - 2); -> recursion block
The recursion block express the abstract rule(s) of recursion. Instead of having those values in variables Fn1 and Fn2, you obtain these values using the same function. Think about a brick wall: your recursive function creates the wall adding a brick to an existing wall. Inside the recursion block, at a certain step, you don't mind who and how the existing wall has been created, you simply add to it a new brick. It happens then that the wall has been created by the same function, one brick at the time.
At the termination block the code is called with some values. What should happen at the end of the process to that value? Speaking about Fibonacci, at the end of the process (n = 1 or n = 0) I have to again add these number to the total. This is done by the recursive block. In other words the termination block gives the concrete values (and not a process on how to obtain them) to the recursion block.
When I have to troubleshoot I print the values at every step, and this is the best solution I've found for me. Then I check that they are what they are supposed to be. For your Fibonacci, I would like to see an output like
Code:
public static int fibonacci( int n ) {
System.out.println( "\nInput value: " + n );
if( n == 0 || n == 1 ) {
System.out.println( "Terminating block value: " + n );
return n;
}
else {
System.out.println( "Recursion block value: fibonacci(" + (n - 1) + ") + fibonacci(" + (n - 2) + ")" );
int result = fibonacci( n - 1 ) + fibonacci( n - 2 );
System.out.println( "Recursion block return value: " + result );
return result;
}
}
Output:
Input value: 4
Recursion block value: fibonacci(3) + fibonacci(2)
Input value: 3
Recursion block value: fibonacci(2) + fibonacci(1)
Input value: 2
Recursion block value: fibonacci(1) + fibonacci(0)
Input value: 1
Terminating block value: 1
Input value: 0
Terminating block value: 0
Recursion block return value: 1
Input value: 1
Terminating block value: 1
Recursion block return value: 2
Input value: 2
Recursion block value: fibonacci(1) + fibonacci(0)
Input value: 1
Terminating block value: 1
Input value: 0
Terminating block value: 0
Recursion block return value: 1
Recursion block return value: 3
You can also find useful to read about Induction, which is strictly related to recursion.
I have this odd issue I can't explain to myself, when using short if inside of return. This code (see below) should return the value 55 but instead it just returns the argument 10 which I passed to it by value.
I already debugged the function and the recursion works as intended but it never adds the + 1 to the return value.
public static int add(int i) {
return i == 0 ? 0 : add(i - 1) + 1;
}
public static void main(String[] args) {
System.out.println(add(10)); // returns 10
}
How come this doesn't work?
Your code does what you're telling it to. At each recursion step it reduces one from the counter and adds 1 to the result - since it's counting i times, it'll return i.
What you're trying to do is sum the numbers from 0 to i. In order to do this you need to add i and not 1 to the sum each time.
public static int add(int i) {
return i == 0 ? 0 : add(i - 1) + i; // <- like this
}
Since this is likely an exercise, consider implementing factorial recursively to make sure you understand the concept (that is, a function that takes n and returns n * (n-1) * (n-2) ... and so on.
This question already has answers here:
Java recursive Fibonacci sequence
(37 answers)
Closed 8 years ago.
I am learning Java and I have this code from the internet and running it in Eclipse:
public class Fibonacci {
public static void main (String [] args) {
for (int counter = 0; counter <= 3; counter++){
System.out.printf("Fibonacci of %d is: %d\n", counter, fibonacci(counter));
}
public static long fibonacci(long number) {
if ((number == 0) || (number == 1))
return number;
else
return fibonacci(number - 1) + fibonacci(number - 2);
}
}
I've tried to understand it but cannot get it. So I run through the code and counter gets passed in through the fibonacci method. As counter starts at 0 and this is what gets passed first, then 1 and I understand the method passes back 0 and then 1.
When it reaches 2: it will return 2-1 + 2-2 = 2 and it does return this.
When it reaches 3: it will return 3-1 + 3-2 = 3 but it does not return 3 it returns 2.
Please can someone explain to me why as I cannot figure this out?
Thanks
First, I have to tell you that this recursive version has a dramatic exponential cost. Once you understand how it works, my advice for you would be to learn about tail recursivity, write a tail-recursive solution, an iterative solution, and compare them to your current method for high values of "number".
Then, your function basically uses the mathematical definition of the Fibonacci sequence :
f0 = 1, f1 = 1, fn = fn-1 + fn-2 for all n >= 2
For example if we call fibonacci(3), this will return fibonacci(2) + fibonacci(1). fibonacci(2) will be executed first and will return fibonacci(1) + fibonnacci(0). Then fibonacci(1) will return immediately 1 since it is a terminal case. It happens the same thing with fibonnacci(0), so now we have computed fibonnacci(2) = 1 + 0 = 1. Let's go back to fibonacci(3) which has been partially evaluated at this point : 1 + fibonnacci(1). We just have to compute fibonnacci(1) and we can finally return 1 + 1 = 2.
Even in this little example, you can see that we evaluated twice fibonacci(1), that is why this version is so slow, it computes many times the same values of the sequence, and it gets worth when "number" is high.
I made a function that computes the sum of digits of an integer. Trying to make the code shorter, I put in comment the if statement to see if it would still work so I can remove it but I get a StackOverflowError, why?
This is my code:
public static int sumDigits(int n) {
//if(n%10==n){ return n;}
return n%10+sumDigits(n/10);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(sumDigits(12611));
}
It never returns, but just recurses deeper and deeper.
You do have a return statement, but before returning it needs to compute the value of the expression n%10+sumDigits(n/10) which involves infinite recursion.
NB: Each time you call the function from itself, the function's context (local variables) are added on top of the stack. The stack has a limited size. Eventually you reach that size and StackOverflowError is the error that's thrown in that condition.
That's because there is no stop clause. You will invoke sumDigits forever.
A recursive function can be defined as expressing an operation as a function of that operation on a value closer to an end point.
Hence, every recursive function needs an end condition at some point, otherwise it will recur infinitely (or, more correctly, until you blow your stack).
The basic definition of the "sum of digits" recursive method (for non-negative values of n) is:
def sumOfDigits (n):
if n < 10:
return n
return (n % 10) + sumOfDigits (n / 10) # assumes integer division.
That first bit, the end condition, is very important, and you seem to have commented yours out for some reason.
If you remove that line, your recursion does not have a base case any longer, which means it never returns.
stackover flow error occurs whenever the address stack in the memory allocated for the program can not store any new address.
so when you recursively call sumDigits() the system keep on saving the last tracked in LIFO manner. so that it becomes easy for the system to get back to the previously address, which is must for the recursion.
If you do recursion infinitely or above the memory constraints, you will suffer stackOverflow error.
The statement that you commented out was the base case for this recursive function. Without a base case this function will loop infinitely.
When you work out the example in the main method you get:
sumDigits(12611)
= 1 + sumDigits(1261)
= 1 + ( 1 + sumDigits(126))
= 1 + ( 1 + (6 + sumDigits(12)))
= 1 + ( 1 + (6 + ( 2 + sumDigits(1))))
= 1 + ( 1 + (6 + ( 2 + ( 1 + sumDigits(0))))) //at this point the commented out if statement would have returned
= 1 + ( 1 + (6 + ( 2 + ( 1 + ( 0 + sumDigits(0))))))
= 1 + ( 1 + (6 + ( 2 + ( 1 + ( 0 + ( 0 + sumDigits(0)))))))
...
At this point the program is stuck in an infinite loop. The commented out statement would have returned when n was 1, thus preventing this situation.
Because you are calling sumDigits() from itself and the code that should cause you to return from infinite recursion is commented out. Uncomment line if(n%10==n){ return n;}
Your recursion does not have a terminating condition. Else, you call the recursive function over and over again, eventually the stack will overflow
Uncomment your stop condition.