Why does the recursive call print '123456' instead of '1'? - java

I'm having trouble understanding how the code is able to recover the remaining integers after they are taken off the original value via x/10. Is there something going on behind the scenes?
// precondition: x >= 0
// Question: What is printed from method call mystery(123456)?
public void mystery(int x) {
if ((x/10) != 0) {
mystery(x/10);
}
System.out.print(x % 10);
}

Each invocation of mystery creates a new stack frame in the JVM. These frames are used to store parameters, local variables, and other data which I'll omit for brevity. In your recursive step (mystery(x / 10)), each newly created stack frame will be holding a successively smaller copy of the result of x / 10. Once the base case is reached, each stack frame will then print the value of its copy of x % 10.
So, for example, mystery(123456):
Frame 1: 123456
Frame 2: 12345
Frame 3: 1234
Frame 4: 123
Frame 5: 12
Frame 6: 1 (Base case is reached! Each frame will now print and return)
Modulo 10 will always print the rightmost digit. So that means after all the frames are finished, you will be left with 123456. If you are expecting 1, then how might you go about modifying your solution? (Hint: think about base cases!)

Each recursive call to mystery() happens before the final print statement that prints the digit. The current state of the program is saved to the stack before the function begins to execute again, so on the last execution of the function, when x/10 = 0, the 1 is printed. Then the program returns to the previous execution of the function, where x = 12, and continues to that print statement to print 12 % 10 = 2. This continues the same way until the program reaches the top level execution of the function.
This page explains recursion and has a useful diagram for the factorial example that shows how functions are called and returned.

Related

Java method executes last print statement three times even though the method is only called once

I'm trying to figure out why this mystery method in Java prints out "43211234". I understand how the program reaches "43211" but I'm not sure how the last System.out.print(x % 10) after the "if" is ran 3 times and for each time, it brings the value of x back to the value it was previous to its current one until it reaches "1234" as the value of x. Could this have something to do with recursion since the method is being called in the "if" 3 times? I'm guessing it's something along those lines because the last executes exactly 3 times as well. I would greatly appreciate your help. Thanks.
class Main {
public static void main(String[] args) {
mystery(1234);
}
public static void mystery(int x) {
System.out.print(x % 10);
if((x / 10) != 0) {
mystery(x / 10);
}
System.out.print(x % 10);
}
}
Not sure if my answer will be any more useful than the previous ones, but I'll try. So, basically, your program uses 2 types of recursion: backward recursion and forward recursion. My answer here is not to describe them to you, but to give you a starting point for more information on them.
Let's trace your program's execution:
mystery(1234) -> print(4) -> mystery(123); At this point, the System.out.print(x % 10); at the end of the method has not been called yet since your program has gone further in the recursion. It will be executed once the program returns from deep inside your recursion, and will be executed with whatever's left.
mystery(1234):
print(4);
mystery(123):
print(3);
mystery(12):
print(2);
mystery(1);
print(1);
print(1); //This is the first System.out.print(x % 10); from the end of the method, that is executed
print(2);
print(3);
print(4);
I understand how the program reaches "43211"
so you know what recursion is.
Everytime mystery() is called, the 1st print is called and then it calls (recursively) itself, before the 2nd print.
When the recursion stops because (x / 10) != 0 is false, the 2nd print is called for the 1st time and then goes back to the previous unfinished recursive calls and executes the remaining print for each one.
Your mystery() method does the following:
print the final digit of the input number (num % 10 gives the last digit)
make a recursive call mystery(x / 10), assuming x / 10 is not zero
then on the way out from the recursion, print the final digit of the input again
Putting this together, with an input of 1234, it means we would print those digits in reverse, then print them again in order.
If this answer still leaves you with doubts, I suggest running your code, beginning with a two digit input like 12, until it is clear what is happening.
This is your recursion stack. This is perfectly fine.
mystery(x / 10); input 1234 prints 4
-> mystery(x / 10); input 123 prints 3
-> mystery(x / 10); input 12 prints 2
-> mystery(x / 10); input 1 prints 1
Just make sure your remove the second sysout that you that you in your code. That is the reason it is printing the same numbers in again.

Printing Recursively

I have this class the just prints an int:
class PRecursion {
public static void main(String[] args){
foo(1);
}
public static void foo(int x){
System.out.println("" + x);
if (x < 3)
foo(x+1);
System.out.println(""+x);
}
}
Output:
1
2
3
3
2
1
Why is it the is printing backwards then decrements?
It is not actually decrementing. What is happening is:
You are calling foo(1).
foo(1) does it's thing and starts a recursion.
Recursion goes on for how long you tell it to (foo(3) in your example)
After the recursion is done, foo(1) still has one statement to execute, and that is:
System.out.println(""+x);
hence you are seeing the print of foo(1) a second time, but after all other prints have been made. The same goes for every other time foo() is being called with a different number. So in the end it looks like it is decrementing, when really you are only printing a second time for the same value, in reverse order.
Try this:
class PRecursion {
public static void main(String[] args){
foo(1);
}
public static void foo(int x){
System.out.println("before " + x);
if (x < 3)
foo(x+1);
System.out.println("after "+x);
}
}
The second print statement doesn't decrement the input. What is happening is it leaves the call of foo(3) before it leaves the call of foo(2) and then finally `foo(1). So it executes the second print statements in the reverse of the order of the first.
If you read out the execution of the program as:
set x=1
print x (i.e. 1)
push x=1 on stack and set x=2 (this is how you can read foo(x+1))
print x (i.e. 2)
push 2 on stack and set x=3
print x (i.e. 3)
Don't push anything (x<3 is false)
print x again (i.e. 3)
pop x=2 off the stack
print x (i.e. 2)
pop x=1 of the stack
print x (i.e. 1)
stripping out the pushing and popping you get:
print 1
print 2
print 3
print 3
print 2
print 1
The value of x is not decrementing but it executes the remaining part of code which looks like decrementing.
System.out.println(" " + x); // 1 2 3
if (x < 3)
foo(x+1);
System.out.println(""+x); //3 2 1
due to recursion it calls the same function again and again and print only the first print statement until the if condition is true but at the end when if is false it stop executing foo(x+1) and exute the remaining print statements as the execution in the last step x is 3 so it prints 3 2 1 .
Maybe this could clear a bit more
Since all the foo(1)-->foo(2)-->foo(3) is executed causing output 1 2 3 the execution is in the last method foo(3) so it started executing the remaining method statement with flow like foo(3)-->foo(2)-->foo(1) printing the remaining print statement which executes looks like all the function backwards resulting in remaining 3 2 1.

Trouble understanding output from a recursive function.

I'm having trouble understanding what happens to this piece of code when it returns. After it outputs 10 9 8 7 6 5 4 3 2 1 0 why does it outputs 1 after 0 and not 0 again?
public static void a(int b){
if(b<0)
return;
System.out.println(b);
a(b-1);
a(b+1);
}
Well you have a(b+1) that means there is no end condition for this case which means StackOverflow. as pointed out in the comment, it is stuck between 0 and 1
If b is less than 0, the execution of the method stops. The Code below the return statement will not be executed.
While this particular example returns a StackOverflowError I don't think that's the kind of answer you're looking for. So pretending that error-causing line wasn't there let me demonstrate what is happening:
public static void a(int b){
if(b<0)
return;
System.out.println(b);
a(b-1);
a(b+1); //assuming this didn't go to infinity
}
The method runs exactly like it reads, but you create sub-tasks.
It checks the if statement, then prints the value of b. Then it runs a(b-1) and then runs a(b+1).
You're getting odd results because then it runs a(b-1) is actually a series of tasks in and of itself. THAT method does all the things I mentioned before and they will all happen BEFORE the first instance ever reaches a(b+1).
Lets say you called a(1);
1 is not less than 0
print 1
a(1-1) //which is zero a(0)
//begin sub-task a(0)
0 is not less than 0
print 0
a(0-1) // which is -1
//begin sub-task a(-1)
-1 is less than 0 so return
a(0+1)
1 is not less than zero
print 1
a(1-1) // which is zero
zero is not less than zero
print zero
a(0-1)
etc. etc.
It may be easier to think of this as
public static void a(int b){
if(b<0)
return;
System.out.println(b);
a(b-1);
System.out.println(b + " is done");
}
This does the following with a(1);:
if(1 < 0) // false
print 1
begin a(1-1) or a(0)
if(0 < 0) // false
print 0
begin a(0-1) or a(-1)
if(-1 < 0) //true so return IE go back to the calling method
print "0 is done"
print "1 is done"
A stack overflow. The call to a(b+1) every time means there will never be a point where the original function can return, or the call to a(b+1), or the call to a(b+1+1) and so on.
The return in this case just finishes the current function/method call, popping things out of the stack and going back up to the previous method call. In other words, that's just your (incomplete) base case. Unless you add a termination condition for the case where b increases, the current base case won't be enough to say stop all recursion and you'll get a SO exception.

Unable to stop the recursion at certain condition

I am doing string (i.e. char array) processing with recursion. In my recursion tree, string located at child has length less than 1 w.r.t its parent and all children at the same height have same length of string but different characters. I want to stop the recursion whenever new string length is greater than or equal to old string length, but i am unable to insert this condition in between recursion. Using System.exit(0) terminates my complete program, which i don't want. Below is my code snippet-
private static void getMinLen(char[] oldStr) {
int len = oldStr.length;
/*
* This terminates the whole program, using break in place of
* System.exit(0) is not effective
*/
if (len < 2)
System.exit(0);
char[] newStr = new char[len - 1];
for (int i = 0; i < len - 1; i++) {
/*
* Every character is matched with its next character and a new char
* array is created having length (len-1)
*/
getMinLen(newStr);
}
}
Actually when i put System.out.println("length=" + len); in the 3rd line. First it prints the length in decreasing order but then length increases, decreases because of recursion. I mean the console shows the following-
length=6
length=5
length=4
length=3
length=2
length=1
length=3
length=3
length=2
length=1
length=4
length=3
length=2
length=1
I simply want to stop my recursion whenever new length becomes greater than or equal to old length.
In every call to getMinLen(oldStr) where the stop condition is not satisfied, you call getMinLen(newStr) several times (in fact as many times as there are elements in newStr). It is not clear from your question or your first comment whether this is intentional. (The fact that your newStr has as many elements as your loop has iterations may suggest it is not.)
If this is not intentional, just move the recursive call one line down, i.e. behind the closing } of the loop.
If it is intentional, the problem may be that you have not understood how recursion works. The fact that the stop condition is fulfilled somewhere is not recorded globally and only relevant for the single call in which the stop condition is fulfilled. This point was itself reached by a recursive call getMinLen's for loop (unless you start with a very short string), and that (outer) for loop continues to execute all subsequent calls to getMinLen--why should it stop? To make it stop, a global boolean variable would help, but be very inelegant. Alternatively, you could make the function return a boolean value and check before each recursive call whether a previous one returned true. You may also, however, reconsider whether a recursive approach is really the most suitable for the problem.
Just replace System.exit(0); by return; at the line you want to exit your method
You should use return.
if (len < 2)
return;
Note that break does only "break" loops or switch statements. To leave a method you have to reach the return statement or end of the method (which acts as an implicit return statement in case the return type is void).
Note that your method does the following:
Assume the initial length is 4:
1. create a new array of length 3 (4-1)
2. call the method recursively 3 times with an array of length 3
3. each new call creates an array of length 2 (3-1)
4. call the method recursively again, now 2 times and with an array of length 2
5. each new call creates an array of length 1 (2-1)
6. call the method recursively again, now once and with an array of length 1
7. each new call creates an array of length 0 (1-1)
8. those methods won't enter the loop since the condition now is `i < 0`, which is false with `i = 0`
Thus, when printing each length, I'd expect the following output
4 //initial call
3 //first iteration of step 2
2 //first iteration of step 4
1 //only iteration of step 6
2 //second iteration of step 4
1
3 //second iteration of step 2
2
1
2
1
3 //third iteration of step 2
2
1
2
1
If you just want one iteration and then stop, why did you put the loop in there?

How does the recursion here work?

Code 1:
public static int fibonacci (int n){
if (n == 0 || n == 1) {
return 1;
} else {
return fibonacci (n-1) + fibonacci (n-2);
}
}
How can you use fibonacci if you haven't gotten done explaining what it is yet? I've been able to understand using recursion in other cases like this:
Code 2:
class two
{
public static void two (int n)
{
if (n>0)
{
System.out.println (n) ;
two (n-1) ;
}
else
{
return ;
}
}
public static void main (String[] arg)
{
two (12) ;
}
}
In the case of code 2, though, n will eventually reach a point at which it doesn't satisfy n>0 and the method will stop calling itself recursively. In the case of code 2, though, I don't see how it would be able to get itself from 1 if n=1 was the starting point to 2 and 3 and 5 and so on. Also, I don't see how the line return fibonacci (n-1) + fibonacci (n-2) would work since fibonacci (n-2) has to contain in some sense fibonacci (n-1) in order to work, but it isn't there yet.
The book I'm looking at says it will work. How does it work?
Well, putting aside what a compiler actually does to your code (it's horrible, yet beautiful) and what how a CPU actually interprets your code (likewise), there's a fairly simple solution.
Consider these text instructions:
To sort numbered blocks:
pick a random block.
if it is the only block, stop.
move the blocks
with lower numbers to the left side,
higher numbers to the right.
sort the lower-numbered blocks.
sort the higher-numbered blocks.
When you get to instructions 4 and 5, you are being asked to start the whole process over again. However, this isn't a problem, because you still know how to start the process, and when it all works out in the end, you've got a bunch of sorted blocks. You could cover the instructions with slips of paper and they wouldn't be any harder to follow.
In the case of code 2 though n will eventualy reach a point at which it doesnt satisfy n>0 and the method will stop calling itself recursivly
to make it look similar you can replace condition if (n == 0 || n == 1) with if (n < 2)
Also i don't see how the line `return fibonacci (n-1) + fibonacci (n-2) would work since fibbonacci n-2 has to contain in some sense fibonacci n-1 in order to wrok but it isn't there yet.
I suspect you wanted to write: "since fibbonacci n-1 has to contain in some sense fibonacci n-2"
If I'm right, then you will see from the example below, that actually fibonacci (n-2) will be called twice for every recursion level (fibonacci(1) in the example):
1. when executing fibonacci (n-2) on the current step
2. when executing fibonacci ((n-1)-1) on the next step
(Also take a closer look at the Spike's comment)
Suppose you call fibonacci(3), then call stack for fibonacci will be like this:
(Veer provided more detailed explanation)
n=3. fibonacci(3)
n=3. fibonacci(2) // call to fibonacci(n-1)
n=2. fibonacci(1) // call to fibonacci(n-1)
n=1. returns 1
n=2. fibonacci(0) // call to fibonacci(n-2)
n=0. returns 1
n=2. add up, returns 2
n=3. fibonacci(1) //call to fibonacci(n-2)
n=1. returns 1
n=3. add up, returns 2 + 1
Note, that adding up in fibonacci(n) takes place only after all functions for smaller args return (i.e. fibonacci(n-1), fibonacci(n-2)... fibonacci(2), fibonacci(1), fibonacci(0))
To see what is going on with call stack for bigger numbers you could run this code.
public static String doIndent( int tabCount ){
String one_tab = new String(" ");
String result = new String("");
for( int i=0; i < tabCount; ++i )
result += one_tab;
return result;
}
public static int fibonacci( int n, int recursion_level )
{
String prefix = doIndent(recursion_level) + "n=" + n + ". ";
if (n == 0 || n == 1){
System.out.println( prefix + "bottommost level, returning 1" );
return 1;
}
else{
System.out.println( prefix + "left fibonacci(" + (n-1) + ")" );
int n_1 = fibonacci( n-1, recursion_level + 1 );
System.out.println( prefix + "right fibonacci(" + (n-2) + ")" );
int n_2 = fibonacci( n-2, recursion_level + 1 );
System.out.println( prefix + "returning " + (n_1 + n_2) );
return n_1 + n_2;
}
}
public static void main( String[] args )
{
fibonacci(5, 0);
}
The trick is that the first call to fibonacci() doesn't return until its calls to fibonacci() have returned.
You end up with call after call to fibonacci() on the stack, none of which return, until you get to the base case of n == 0 || n == 1. At this point the (potentially huge) stack of fibonacci() calls starts to unwind back towards the first call.
Once you get your mind around it, it's kind of beautiful, until your stack overflows.
"How can you use Fibonacci if you haven't gotten done explaining what it is yet?"
This is an interesting way to question recursion. Here's part of an answer: While you're defining Fibonacci, it hasn't been defined yet, but it has been declared. The compiler knows that there is a thing called Fibonacci, and that it will be a function of type int -> int and that it will be defined whenever the program runs.
In fact, this is how all identifiers in C programs work, not just recursive ones. The compiler determines what things have been declared, and then goes through the program pointing uses of those things to where the things actually are (gross oversimplification).
Let me walkthrough the execution considering n=3. Hope it helps.
When n=3 => if condition fails and else executes
return fibonacci (2) + fibonacci (1);
Split the statement:
Find the value of fibonacci(2)
Find the value of fibonacci(1)
// Note that it is not fib(n-2) and it is not going to require fib(n-1) for its execution. It is independent. This applies to step 1 also.
Add both values
return the summed up value
The way it gets executed(Expanding the above four steps):
Find the value of fibonacci(2)
if fails, else executes
fibonacci(1)
if executes
value '1' is returned to step 1.2. and the control goes to step 1.3.
fibonacci(0)
if executes
value '1' is returned to step 1.3. and the control goes to step 1.4.
Add both
sum=1+1=2 //from steps 1.2.2. and 1.3.2.
return sum // value '2' is returned to step 1. and the control goes to step 2
Find the value of fibonacci(1)
if executes
value '1' is returned
Add both values
sum=2+1 //from steps 1.5. and 2.2.
return the summed up value //sum=3
Try to draw an illustration yourself, you will eventually see how it works. Just be clear that when a function call is made, it will fetch its return value first. Simple.
Try debugging and use watches to know the state of the variable
Understanding recursion requires also knowing how the call stack works i.e. how functions call each other.
If the function didn't have the condition to stop if n==0 or n==1, then the function would call itself recursively forever.
It works because eventually, the function is going to petter out and return 1. at that point, the return fibonacci (n-1) + fibonacci (n-2) will also return with a value, and the call stack gets cleaned up really quickly.
I'll explain what your PC is doing when executing that piece of code with an example:
Imagine you're standing in a very big room. In the room next to this room you have massive amounts of paper, pens and tables. Now we're going to calculate fibonacci(3):
We take a table and put it somewhere in the room. On the table we place a paper and we write "n=3" on it. We then ask ourselves "hmm, is 3 equal to 0 or 1?". The answer is no, so we will do "return fibonacci (n-1) + fibonacci (n-2);".
There's a problem however, we have no idea what "fibonacci (n-1)" and "fibonacci (n-2)" actually do. Hence, we take two more tables and place them to the left and right of our original table with a paper on both of them, saying "n=2" and "n=1".
We start with the left table, and wonder "is 2 equal to 0 or 1?". Of course, the answer is no, so we will once again place two tables next to this table, with "n=1" and "n=0" on them.
Still following? This is what the room looks like:
n=1
n=2 n=3 n=1
n=0
We start with the table with "n=1", and hey, 1 is equal to 1, so we can actually return something useful! We write "1" on another paper and go back to the table with "n=2" on it. We place the paper on the table and go to the other table, because we still don't know what we're going to do with that other table.
"n=0" of course returns 1 as well, so we write that on a paper, go back to the n=2 table and put the paper there. At this point, there are two papers on this table with the return values of the tables with "n=1" and "n=0" on them, so we can compute that the result of this method call is actually 2, so we write it on a paper and put it on the table with "n=3" on it.
We then go to the table with "n=1" on it all the way to the right, and we can immediately write 1 on a paper and put it back on the table with "n=3" on it. After that, we finally have enough information to say that fibonacci(3) returns 3.
It's important to know that the code you are writing is nothing more than a recipe. All the compiler does is transform that recipe in another recipe your PC can understand. If the code is completely bogus, like this:
public static int NotUseful()
{
return NotUseful();
}
will simply loop endlessly, or as in my example, you'll keep on placing more and more tables without actually getting anywhere useful. Your compiler doesn't care what fibonacci(n-1) or fibonacci(n-2) actually do.

Categories