Using Recursion to compute the number of something to print - java

I learning recursion and there is an example which I solve writing the * character a certain amount of times.
For example: if you were to pass in the number 3, it should print 2^3 stars so it would print out 8 stars.
I should print it 2 ^ k times where k is a passed integer. The answer to the question is:
public String printStars(int k) {
if (k == 0)
return "*";
else
return printStars(k - 1) + printStars(k - 1);
}
I cant seem to understand the call stack and how that solves the problem, the way I view it, when I pass in 3 for int k, it would do n - 1 3 times till it hits the base case, and would return 2 stars to the call before that, and since it took 3 levels to get that deep, it would print 3 x 2 stars so it would print 6 stars. It's strange because most other recursion comes easily to me but this is confusing.

I guess it must always be k or n?
How the recursion works: It spanns a tree:
Each call to printStars leads to one * (2^0) or two * (2^1).
If you call printStars(4):
Recursion level 4 ist != 0 so it returns the contraction of two separate calls of itself, each with parameter (3).
Recursion level 3 ist != 0 so it returns the contraction of two separate calls of itself, each with parameter (2).
Recursion level 2 ist != 0 so it returns the contraction of two separate calls of itself, each with parameter (1).
Recursion level 1 ist != 0 so it returns the contraction of two separate calls of itself, each with parameter (0).
Recursion level 0 ist == 0 so each call return with one *.
Back in recursion level 1 we receive two * and contract and return them.
Back in recursion level 2 we receive two ** and contract and return them.
Back in recursion level 3 we receive two **** and contract and return them.
Back in recursion level 4 we receive two ******** and contract and return them.
So the caller receives '***************' 2^4=16 *'s
caller |
k=4 / \ (just call yourself 2 times an return contraction of both calls)
k=3 / \ / \ (just call yourself 2 times an return contraction of both calls)
k=2 / \ / \ / \ / \ (just call yourself 2 times an return contraction of both calls)
k=1 /\ /\ /\ /\ /\ /\ /\ /\ (just call yourself 2 times an return contraction of both calls)
k=0 ** ** ** ** ** ** ** ** (just return 2^0 = 1 '*')

I think the easy way to see it is to just expand each function call:
When k = 3 the return statement evaluates to printStars(2) + printStars(2).
So it'll call the printStars(2) on the left first which will evaluate to:
printStars(1) + printStars(1) + printStars(2)
Again, let's expand the left one first:
printStars(0) + printStars(0) + printStars(1) + printStars(2)
printStars(0) will finally evaluate to "*" so we'd have
"*" + "*" + printStars(1) + printStars(2) == "**" + printStars(1) + printStars(2).
And we've already seen that printStars(1) == "**" so we have:
"****" + printStars(2). And we already know what printStars(2) will resolve to.

Just follow the code through:
It should be clear that in the non-base case:
printStars(k).length() == 2 * printStars(k - 1).length()
since the value in that case is given by
return printStars(k - 1) + printStars(k - 1);
Using this observation, we can prove by induction that:
printStars(k).length() == 2^k
(where ^ denotes power, rather than bitwise XOR)
It is true in the base case that printStars(0).length() == 2^0
Assuming that printStars(k - 1).length() == 2^(k-1), printStars(k).length() == 2 * printStars(k - 1).length() == 2^k
QED.

Related

What does a recursive method in java return? [duplicate]

As the title explains I have a very fundamental programming question which I have just not been able to grok yet. Filtering out all of the (extremely clever) "In order to understand recursion, you must first understand recursion." replies from various online threads I still am not quite getting it.
Understanding that when faced with not knowing what we don't know, we can tend to ask the wrong questions or ask the right questions incorrectly I will share what I "think" my question is in hopes that someone with a similar outlook can share some bit of knowledge that will help turn on the recursive light bulb for me!
Here is the function (the syntax is written in Swift):
func sumInts(a: Int, b: Int) -> Int {
if (a > b) {
return 0
} else {
return a + sumInts(a: a + 1, b: b)
}
}
We'll use 2 and 5 as our arguments:
println(sumInts(a: 2, b: 5))
Obviously the answer is 14. But I'm not clear on how that value is achieved.
These are my 2 hangups:
The function is called recursively until a condition is met. That condition is a > b. When this condition is met, return 0. At first glance, I would expect the return value to be 0 which is obviously incorrect.
Printing out the value of 'a' on each iteration yields a value which I would expect: 2, 3, 4, 5 (at which point 5+1 > b which meets the first condition: a > b) but I still don't see how the value of 14 is achieved.
My first thought is that something similar to the following is happening magically:
var answer = a;
answer += a+1 until a > b;
return answer;
So ruling out magic, I'm just not getting something. I would love to understand what's happening more than just implicitly.
If someone could kindly explain what technically happens during this kind of function and why the result isn't 0 and how, eventually, a + sumInts(a: a + 1, b: b) = 14, I would be forever in your debt.
1.The function is called recursively until a condition is met. That condition is a > b. When this condition is met, return 0. At first glance, I would expect the return value to be 0 which is obviously incorrect.
Here is what the computer computing sumInts(2,5) would think if it were able to:
I want to compute sumInts(2, 5)
for this, I need to compute sumInts(3, 5)
and add 2 to the result.
I want to compute sumInts(3, 5)
for this, I need to compute sumInts(4, 5)
and add 3 to the result.
I want to compute sumInts(4, 5)
for this, I need to compute sumInts(5, 5)
and add 4 to the result.
I want to compute sumInts(5, 5)
for this, I need to compute sumInts(6, 5)
and add 5 to the result.
I want to compute sumInts(6, 5)
since 6 > 5, this is zero.
The computation yielded 0, therefore I shall return 5 = 5 + 0.
The computation yielded 5, therefore I shall return 9 = 4 + 5.
The computation yielded 9, therefore I shall return 12 = 3 + 9.
The computation yielded 12, therefore I shall return 14 = 2 + 12.
As you see, some call to the function sumInts actually returns 0 however this not the final value because the computer still has to add 5 to that 0, then 4 to the result, then 3, then 2, as described by the four last sentences of the thoughts of our computer. Note that in the recursion, the computer does not only have to compute the recursive call, it also has to remember what to do with the value returned by the recursive call. There is a special area of computer's memory called the stack where this kind of information is saved, this space is limited and functions that are too recursive can exhaust the stack: this is the stack overflow giving its name to our most loved website.
Your statement seems to make the implicit assumption that the computer forgets what it were at when doing a recursive call, but it does not, this is why your conclusion does not match your observation.
2.Printing out the value of 'a' on each iteration yields a value which I would expect: 2, 3, 4, 5 (at which point 5+1 > b which meets the first condition: a > b) but I still don't see how the value of 14 is achieved.
This is because the return value is not an a itself but the sum of the value of a and the value returned by the recursive call.
I think the confusion is stemming from thinking of it as "the same function" being called many times. If you think of it as "many copies of the same function being called", then it may be clearer:
Only one copy of the function ever returns 0, and it's not the first one (it's the last one). So the result of calling the first one is not 0.
For the second bit of confusion, I think it will be easier to spell out the recursion in English. Read this line:
return a + sumInts(a + 1, b: b)
as "return the value of 'a' plus (the return value of another copy of the function, which is the copy's value of 'a' plus (the return value of another copy of the function, which is the second copy's value of 'a' plus (...", with each copy of the function spawning a new copy of itself with a increased by 1, until the a > b condition is met.
By the time you reach the the a > b condition being true, you have a (potentially arbitrarily) long stack of copies of the function all in the middle of being run, all waiting on the result of the next copy to find out what they should add to 'a'.
(edit: also, something to be aware of is that the stack of copies of the function I mention is a real thing that takes up real memory, and will crash your program if it gets too large. The compiler can optimize it out in some cases, but exhausting stack space is a significant and unfortunate limitation of recursive functions in many languages)
To understand recursion you must think of the problem in a different way. Instead of a large logical sequence of steps that makes sense as a whole you instead take a large problem and break up into smaller problems and solve those, once you have an answer for the sub problems you combine the results of the sub problems to make the solution to the bigger problem. Think of you and your friends needing to count the number of marbles in a huge bucket. You do each take a smaller bucket and go count those individually and when you are done you add the totals together.. Well now if each of you find some friend and split the buckets further, then you just need to wait for these other friends to figure out their totals, bring it back to each of you, you add it up. And so on. The special case is when you only get 1 marble to count then you just return it back and say 1. let the other people above you do the adding you are done.
You must remember every time the function calls itself recursively it creates a new context with a subset of the problem, once that part is resolved it gets returned so that the previous iteration can complete.
Let me show you the steps:
sumInts(a: 2, b: 5) will return: 2 + sumInts(a: 3, b: 5)
sumInts(a: 3, b: 5) will return: 3 + sumInts(a: 4, b: 5)
sumInts(a: 4, b: 5) will return: 4 + sumInts(a: 5, b: 5)
sumInts(a: 5, b: 5) will return: 5 + sumInts(a: 6, b: 5)
sumInts(a: 6, b: 5) will return: 0
once sumInts(a: 6, b: 5) has executed, the results can be computed so going back up the chain with the results you get:
sumInts(a: 6, b: 5) = 0
sumInts(a: 5, b: 5) = 5 + 0 = 5
sumInts(a: 4, b: 5) = 4 + 5 = 9
sumInts(a: 3, b: 5) = 3 + 9 = 12
sumInts(a: 2, b: 5) = 2 + 12 = 14.
Another way to represent the structure of the recursion:
sumInts(a: 2, b: 5) = 2 + sumInts(a: 3, b: 5)
sumInts(a: 2, b: 5) = 2 + 3 + sumInts(a: 4, b: 5)
sumInts(a: 2, b: 5) = 2 + 3 + 4 + sumInts(a: 5, b: 5)
sumInts(a: 2, b: 5) = 2 + 3 + 4 + 5 + sumInts(a: 6, b: 5)
sumInts(a: 2, b: 5) = 2 + 3 + 4 + 5 + 0
sumInts(a: 2, b: 5) = 14
Recursion is a tricky topic to understand and I don't think I can fully do it justice here. Instead, I'll try to focus on the particular piece of code you have here and try to describe both the intuition for why the solution works and the mechanics of how the code computes its result.
The code you've given here solves the following problem: you want to know the sum of all the integers from a to b, inclusive. For your example, you want the sum of the numbers from 2 to 5, inclusive, which is
2 + 3 + 4 + 5
When trying to solve a problem recursively, one of the first steps should be to figure out how to break the problem down into a smaller problem with the same structure. So suppose that you wanted to sum up the numbers from 2 to 5, inclusive. One way to simplify this is to notice that the above sum can be rewritten as
2 + (3 + 4 + 5)
Here, (3 + 4 + 5) happens to be the sum of all the integers between 3 and 5, inclusive. In other words, if you want to know the sum of all the integers between 2 and 5, start by computing the sum of all the integers between 3 and 5, then add 2.
So how do you compute the sum of all the integers between 3 and 5, inclusive? Well, that sum is
3 + 4 + 5
which can be thought of instead as
3 + (4 + 5)
Here, (4 + 5) is the sum of all the integers between 4 and 5, inclusive. So, if you wanted to compute the sum of all the numbers between 3 and 5, inclusive, you'd compute the sum of all the integers between 4 and 5, then add 3.
There's a pattern here! If you want to compute the sum of the integers between a and b, inclusive, you can do the following. First, compute the sum of the integers between a + 1 and b, inclusive. Next, add a to that total. You'll notice that "compute the sum of the integers between a + 1 and b, inclusive" happens to be pretty much the same sort of problem we're already trying to solve, but with slightly different parameters. Rather than computing from a to b, inclusive, we're computing from a + 1 to b, inclusive. That's the recursive step - to solve the bigger problem ("sum from a to b, inclusive"), we reduce the problem to a smaller version of itself ("sum from a + 1 to b, inclusive.").
If you take a look at the code you have above, you'll notice that there's this step in it:
return a + sumInts(a + 1, b: b)
This code is simply a translation of the above logic - if you want to sum from a to b, inclusive, start by summing a + 1 to b, inclusive (that's the recursive call to sumInts), then add a.
Of course, by itself this approach won't actually work. For example, how would you compute the sum of all the integers between 5 and 5 inclusive? Well, using our current logic, you'd compute the sum of all the integers between 6 and 5, inclusive, then add 5. So how do you compute the sum of all the integers between 6 and 5, inclusive? Well, using our current logic, you'd compute the sum of all the integers between 7 and 5, inclusive, then add 6. You'll notice a problem here - this just keeps on going and going!
In recursive problem solving, there needs to be some way to stop simplifying the problem and instead just go solve it directly. Typically, you'd find a simple case where the answer can be determined immediately, then structure your solution to solve simple cases directly when they arise. This is typically called a base case or a recursive basis.
So what's the base case in this particular problem? When you're summing up integers from a to b, inclusive, if a happens to be bigger than b, then the answer is 0 - there aren't any numbers in the range! Therefore, we'll structure our solution as follows:
If a > b, then the answer is 0.
Otherwise (a ≤ b), get the answer as follows:
Compute the sum of the integers between a + 1 and b.
Add a to get the answer.
Now, compare this pseudocode to your actual code:
func sumInts(a: Int, b: Int) -> Int {
if (a > b) {
return 0
} else {
return a + sumInts(a + 1, b: b)
}
}
Notice that there's almost exactly a one-to-one map between the solution outlined in pseudocode and this actual code. The first step is the base case - in the event that you ask for the sum of an empty range of numbers, you get 0. Otherwise, compute the sum between a + 1 and b, then go add a.
So far, I've given just a high-level idea behind the code. But you had two other, very good questions. First, why doesn't this always return 0, given that the function says to return 0 if a > b? Second, where does the 14 actually come from? Let's look at these in turn.
Let's try a very, very simple case. What happens if you call sumInts(6, 5)? In this case, tracing through the code, you see that the function just returns 0. That's the right thing to do, to - there aren't any numbers in the range. Now, try something harder. What happens when you call sumInts(5, 5)? Well, here's what happens:
You call sumInts(5, 5). We fall into the else branch, which return the value of `a + sumInts(6, 5).
In order for sumInts(5, 5) to determine what sumInts(6, 5) is, we need to pause what we're doing and make a call to sumInts(6, 5).
sumInts(6, 5) gets called. It enters the if branch and returns 0. However, this instance of sumInts was called by sumInts(5, 5), so the return value is communicated back to sumInts(5, 5), not to the top-level caller.
sumInts(5, 5) now can compute 5 + sumInts(6, 5) to get back 5. It then returns it to the top-level caller.
Notice how the value 5 was formed here. We started off with one active call to sumInts. That fired off another recursive call, and the value returned by that call communicated the information back to sumInts(5, 5). The call to sumInts(5, 5) then in turn did some computation and returned a value back to the caller.
If you try this with sumInts(4, 5), here's what will happen:
sumInts(4, 5) tries to return 4 + sumInts(5, 5). To do that, it calls sumInts(5, 5).
sumInts(5, 5) tries to return 5 + sumInts(6, 5). To do that, it calls sumInts(6, 5).
sumInts(6, 5) returns 0 back to sumInts(5, 5).</li>
<li>sumInts(5, 5)now has a value forsumInts(6, 5), namely 0. It then returns5 + 0 = 5`.
sumInts(4, 5) now has a value for sumInts(5, 5), namely 5. It then returns 4 + 5 = 9.
In other words, the value that's returned is formed by summing up values one at a time, each time taking one value returned by a particular recursive call to sumInts and adding on the current value of a. When the recursion bottoms out, the deepest call returns 0. However, that value doesn't immediately exit the recursive call chain; instead, it just hands the value back to the recursive call one layer above it. In that way, each recursive call just adds in one more number and returns it higher up in the chain, culminating with the overall summation. As an exercise, try tracing this out for sumInts(2, 5), which is what you wanted to begin with.
Hope this helps!
You've got some good answers here so far, but I'll add one more that takes a different tack.
First off, I have written many articles on simple recursive algorithms that you might find interesting; see
http://ericlippert.com/tag/recursion/
http://blogs.msdn.com/b/ericlippert/archive/tags/recursion/
Those are in newest-on-top order, so start from the bottom.
Second, so far all of the answers have described recursive semantics by considering function activation. That each, each call makes a new activation, and the recursive call executes in the context of this activation. That is a good way to think of it, but there is another, equivalent way: smart text seach-and-replace.
Let me rewrite your function into a slightly more compact form; don't think of this as being in any particular language.
s = (a, b) => a > b ? 0 : a + s(a + 1, b)
I hope that makes sense. If you're not familiar with the conditional operator, it is of the form condition ? consequence : alternative and its meaning will become clear.
Now we wish to evaluate s(2,5) We do so by doing a textual replacing of the call with the function body, then replace a with 2 and b with 5:
s(2, 5)
---> 2 > 5 ? 0 : 2 + s(2 + 1, 5)
Now evaluate the conditional. We textually replace 2 > 5 with false.
---> false ? 0 : 2 + s(2 + 1, 5)
Now textually replace all false conditionals with the alternative and all true conditionals with the consequence. We have only false conditionals, so we textually replace that expression with the alternative:
---> 2 + s(2 + 1, 5)
Now, to save me having to type all those + signs, textually replace constant arithmetic with its value. (This is a bit of a cheat, but I don't want to have to keep track of all the parentheses!)
---> 2 + s(3, 5)
Now search-and-replace, this time with the body for the call, 3 for a and 5 for b. We'll put the replacement for the call in parentheses:
---> 2 + (3 > 5 ? 0 : 3 + s(3 + 1, 5))
And now we just keep on doing those same textual substitution steps:
---> 2 + (false ? 0 : 3 + s(3 + 1, 5))
---> 2 + (3 + s(3 + 1, 5))
---> 2 + (3 + s(4, 5))
---> 2 + (3 + (4 > 5 ? 0 : 4 + s(4 + 1, 5)))
---> 2 + (3 + (false ? 0 : 4 + s(4 + 1, 5)))
---> 2 + (3 + (4 + s(4 + 1, 5)))
---> 2 + (3 + (4 + s(5, 5)))
---> 2 + (3 + (4 + (5 > 5 ? 0 : 5 + s(5 + 1, 5))))
---> 2 + (3 + (4 + (false ? 0 : 5 + s(5 + 1, 5))))
---> 2 + (3 + (4 + (5 + s(5 + 1, 5))))
---> 2 + (3 + (4 + (5 + s(6, 5))))
---> 2 + (3 + (4 + (5 + (6 > 5 ? 0 : s(6 + 1, 5)))))
---> 2 + (3 + (4 + (5 + (true ? 0 : s(6 + 1, 5)))))
---> 2 + (3 + (4 + (5 + 0)))
---> 2 + (3 + (4 + 5))
---> 2 + (3 + 9)
---> 2 + 12
---> 14
All we did here was just straightforward textual substitution. Really I shouldn't have substituted "3" for "2+1" and so on until I had to, but pedagogically it would have gotten hard to read.
Function activation is nothing more than replacing the function call with the body of the call, and replacing the formal parameters with their corresponding arguments. You have to be careful about introducing parentheses intelligently, but aside from that, it's just text replacement.
Of course, most languages do not actually implement activation as text replacement, but logically that's what it is.
So what then is an unbounded recursion? A recursion where the textual substitution doesn't stop! Notice how eventually we got to a step where there was no more s to replace, and we could then just apply the rules for arithmetic.
The way that I usually figure out how a recursive function works is by looking at the base case and working backwards. Here's that technique applied to this function.
First the base case:
sumInts(6, 5) = 0
Then the call just above that in the call stack:
sumInts(5, 5) == 5 + sumInts(6, 5)
sumInts(5, 5) == 5 + 0
sumInts(5, 5) == 5
Then the call just above that in the call stack:
sumInts(4, 5) == 4 + sumInts(5, 5)
sumInts(4, 5) == 4 + 5
sumInts(4, 5) == 9
And so on:
sumInts(3, 5) == 3 + sumInts(4, 5)
sumInts(3, 5) == 3 + 9
sumInts(3, 5) == 12
And so on:
sumInts(2, 5) == 2 + sumInts(3, 5)
sumInts(4, 5) == 2 + 12
sumInts(4, 5) == 14
Notice that we've arrived at our original call to the function sumInts(2, 5) == 14
The order in which these calls are executed:
sumInts(2, 5)
sumInts(3, 5)
sumInts(4, 5)
sumInts(5, 5)
sumInts(6, 5)
The order in which these calls return:
sumInts(6, 5)
sumInts(5, 5)
sumInts(4, 5)
sumInts(3, 5)
sumInts(2, 5)
Note that we came to a conclusion about how the function operates by tracing the calls in the order that they return.
Recursion. In Computer Science recursion is covered in depth under the topic of Finite Automata.
In its simplest form it is a self reference. For example, saying that "my car is a car" is a recursive statement. The problem is that the statement is an infinite recursion in that it will never end. The definition in the statement of a "car" is that it is a "car" so it may be substituted. However, there is no end because in the case of substitution, it still becomes "my car is a car".
This could be different if the statement were "my car is a bentley. my car is blue." In which case the substitution in the second situation for car could be "bentley" resulting in "my bentley is blue". These types of substitutions are mathematically explained in Computer Science through Context-Free Grammars.
The actual substitution is a production rule. Given that the statement is represented by S and that car is a variable which can be a "bentley" this statement can be recursively reconstructed.
S -> "my"S | " "S | CS | "is"S | "blue"S | ε
C -> "bentley"
This can be constructed in multiple ways, as each | means there is a choice. S can be replaced by any one of those choices, and S always starts empty. The ε means to terminate the production. Just as S can be replaced, so can other variables (there is only one and it is C which would represent "bentley").
So starting with S being empty, and replacing it with the first choice "my"S S becomes
"my"S
S can still be substituted as it represents a variable. We could choose "my" again, or ε to end it, but lets continue making our original statement. We choose the space which means S is replaced with " "S
"my "S
Next lets choose C
"my "CS
And C only has one choice for replacement
"my bentley"S
And the space again for S
"my bentley "S
And so on "my bentley is"S, "my bentley is "S, "my bentley is blue"S, "my bentley is blue" (replacing S for ε ends the production) and we have recursively built our statement "my bentley is blue".
Think of recursion as these productions and replacements. Each step in the process replaces its predecessor in order to produce the end result. In the exact example of the recursive sum from 2 to 5, you end up with the production
S -> 2 + A
A -> 3 + B
B -> 4 + C
C -> 5 + D
D -> 0
This becomes
2 + A
2 + 3 + B
2 + 3 + 4 + C
2 + 3 + 4 + 5 + D
2 + 3 + 4 + 5 + 0
14
Think recursion as a multiple clones doing same thing...
You ask to clone[1]: "sum numbers between 2 and 5"
+ clone[1] it knows that: result is 2 + "sum numbers between 3 and 5". so it asks to clone[2] to return: "sum numbers between 3 and 5"
| + clone[2] it knows that: result is 3 + "sum numbers between 4 and 5". so it asks to clone[3] to return: "sum numbers between 4 and 5"
| | + clone[3] it knows that: result is 4 + "sum numbers between 5 and 5". so it asks to clone[4] to return: "sum numbers between 5 and 5"
| | | + clone[4] it knows that: result is 5 + "sum numbers between 6 and 5". so it asks to clone[5] to return: "sum numbers between 6 and 5"
| | | | clone[5] it knows that: it can't sum, because 6 is larger than 5. so he returns 0 as result.
| | | + clone[4] it gets the result from clone[5] (=0) and sums: 5 + 0, returning 5
| | + clone[3] it gets the result from clone[4] (=5) and sums: 4 + 5, returning 9
| + clone[2] it gets the result from clone[3] (=9) and sums: 3 + 9, returning 12
+ clone[1] it gets the result from clone[2] (=12) and sums: 2 + 12, returning 14
and voilá!!
I'll give it a go.
Executing the equation a + sumInts(a+1, b), I will show how the final answer is 14.
//the sumInts function definition
func sumInts(a: Int, b: Int) -> Int {
if (a > b) {
return 0
} else {
return a + sumInts(a + 1, b)
}
}
Given: a = 2 and b = 5
1) 2 + sumInts(2+1, 5)
2) sumInts(3, 5) = 12
i) 3 + sumInts(3+1, 5)
ii) 4 + sumInts(4+1, 5)
iii) 5 + sumInts(5+1, 5)
iv) return 0
v) return 5 + 0
vi) return 4 + 5
vii) return 3 + 9
3) 2 + 12 = 14.
Let us know if you have any further questions.
Here's another example of recursive functions in the following example.
A man has just graduated college.
t is the amount of time in years.
The total actual number of years worked before retiring, can be calculated as follows:
public class DoIReallyWantToKnow
{
public int howLongDoIHaveToWork(int currentAge)
{
const int DESIRED_RETIREMENT_AGE = 65;
double collectedMoney = 0.00; //remember, you just graduated college
double neededMoneyToRetire = 1000000.00
t = 0;
return work(t+1);
}
public int work(int time)
{
collectedMoney = getCollectedMoney();
if(currentAge >= DESIRED_RETIREMENT_AGE
&& collectedMoney == neededMoneyToRetire
{
return time;
}
return work(time + 1);
}
}
And that should be just enough to depress anyone, lol. ;-P
A little bit off-topic, I know, but... try looking up recursion in Google... You'll see by example what it means :-)
Earlier versions of Google returned the following text (cited from memory):
Recursion
See Recursion
On September 10th 2014, the joke about recursion has been updated:
Recursion
Did you mean: Recursion
For another reply, see this answer.
One really good tip I came across in learning and really understanding recursion is to spend some time learning a language that doesn't have any form of loop construct other than via recursion. That way you'll get a great feel for how to USE recursion via practice.
I followed http://www.htdp.org/ which, as well as being a Scheme tutorial, is also a great introduction on how to design programs in terms of the architecture and design.
But basically, you need to invest some time. Without a 'firm' grasp of recursion certain algorithms, such as backtracking, will always seem 'hard' or even 'magic' to you. So, persevere. :-D
I hope this helps and Good Luck!
I think the best way to understand recursive functions is realizing that they are made to process recursive data structures. But in your original function sumInts(a: Int, b: Int) that calculates recursively the sum of numbers from a to b, it seems not to be a recursive data structure... Let's try a slightly modified version sumInts(a: Int, n: Int) where n is how many numbers you'll add.
Now, sumInts is recursive over n, a natural number. Still not a recursive data, right? Well, a natural number could be considered a recursive data structre using Peano axioms:
enum Natural = {
case Zero
case Successor(Natural)
}
So, 0 = Zero, 1 = Succesor(Zero), 2 = Succesor(Succesor(Zero)), and so on.
Once you have a a recursive data structure, you have the template for the function. For each non recursive case, you can calculate the value directly. For the recursive cases you assume that the recursive function is already working and use it to calculate the case, but deconstructing the argument. In the case of Natural, it means that instead of Succesor(n) we'll use n, or equivalently, instead of n we'll use n - 1.
// sums n numbers beginning from a
func sumInts(a: Int, n: Int) -> Int {
if (n == 0) {
// non recursive case
} else {
// recursive case. We use sumInts(..., n - 1)
}
}
Now the recursive function is simpler to program. First, the base case, n=0. What should we return if we want to add no numbers? The answer is, of course 0.
What about the recursive case? If we want to add n numbers beginning with a and we already have a working sumInts function that works for n-1? Well, we need to add a and then invoke sumInts with a + 1, so we end with:
// sums n numbers beginning from a
func sumInts(a: Int, n: Int) -> Int {
if (n == 0) {
return 0
} else {
return a + sumInts(a + 1, n - 1)
}
}
The nice thing is that now you shouldn't need to think in the low level of recursion. You just need to verify that:
For the base cases of the recursive data, it calculates the answer without using recursion.
For the recursive cases of the recursive data, it calculates the answer using recursion over the destructured data.
You might be interested in Nisan and Schocken's implementation of functions. The linked pdf is part of a free online course. It describes the second part of a virtual machine implementation in which the student should write a virtual-machine-language-to-machine-language compiler. The function implementation they propose is capable of recursion because it is stack-based.
To introduce you to the function implementation: Consider the following virtual machine code:
If Swift compiled to this virtual machine language, then the following block of Swift code:
mult(a: 2, b: 3) - 4
would compile down to
push constant 2 // Line 1
push constant 3 // Line 2
call mult // Line 3
push constant 4 // Line 4
sub // Line 5
The virtual machine language is designed around a global stack. push constant n pushes an integer onto this global stack.
After executing lines 1 and 2, the stack looks like:
256: 2 // Argument 0
257: 3 // Argument 1
256 and 257 are memory addresses.
call mult pushes the return line number (3) onto the stack and allocates space for the function's local variables.
256: 2 // argument 0
257: 3 // argument 1
258: 3 // return line number
259: 0 // local 0
...and it goes-to the label function mult. The code inside mult is executed. As a result of executing that code we compute the product of 2 and 3, which is stored in the function's 0th local variable.
256: 2 // argument 0
257: 3 // argument 1
258: 3 // return line number
259: 6 // local 0
Just before returning from mult, you will notice the line:
push local 0 // push result
We will push the product onto the stack.
256: 2 // argument 0
257: 3 // argument 1
258: 3 // return line number
259: 6 // local 0
260: 6 // product
When we return, the following happens:
Pop the last value on the stack to the memory address of the 0th argument (256 in this case). This happens to be the most convenient place to put it.
Discard everything on the stack up to the address of the 0th argument.
Go-to the return line number (3 in this case) and then advance.
After returning we are ready to execute line 4, and our stack looks like this:
256: 6 // product that we just returned
Now we push 4 onto the stack.
256: 6
257: 4
sub is a primitive function of the virtual machine language. It takes two arguments and returns its result in the usual address: that of the 0th argument.
Now we have
256: 2 // 6 - 4 = 2
Now that you know how a function call works, it is relatively simple to understand how recursion works. No magic, just a stack.
I have implemented your sumInts function in this virtual machine language:
function sumInts 0 // `0` means it has no local variables.
label IF
push argument 0
push argument 1
lte
if-goto ELSE_CASE
push constant 0
return
label ELSE_CASE
push constant 2
push argument 0
push constant 1
add
push argument 1
call sumInts // Line 15
add // Line 16
return // Line 17
// End of function
Now I will call it:
push constant 2
push constant 5
call sumInts // Line 21
The code executes and we get all the way to the stopping point where lte returns false. This is what the stack looks like at this point:
// First invocation
256: 2 // argument 0
257: 5 // argument 1
258: 21 // return line number
259: 2 // augend
// Second
260: 3 // argument 0
261: 5 // argument 1
262: 15 // return line number
263: 3 // augend
// Third
264: 4 // argument 0
265: 5 // argument 1
266: 15 // return line number
267: 4 // augend
// Fourth
268: 5 // argument 0
269: 5 // argument 1
270: 15 // return line number
271: 5 // augend
// Fifth
272: 6 // argument 0
273: 5 // argument 1
274: 15 // return line number
275: 0 // return value
Now let's "unwind" our recursion. return 0 and goto line 15 and advance.
271: 5
272: 0
Line 16: add
271: 5
Line 17: return 5 and goto line 15 and advance.
267: 4
268: 5
Line 16: add
267: 9
Line 17: return 9 and goto line 15 and advance.
263: 3
264: 9
Line 16: add
263: 12
Line 17: return 12 and goto line 15 and advance.
259: 2
260: 12
Line 16: add
259: 14
Line 17: return 14 and goto line 21 and advance.
256: 14
There you have it. Recursion: Glorified goto.
There are already a lot of good answers. Still I am giving a try.
When called, a function get a memory-space allotted, which is stacked upon the memory-space of the caller function. In this memory-space, the function keeps the parameters passed to it, the variables and their values. This memory-space vanishes along with the ending return call of the function. As the idea of stack goes, the memory-space of the caller function now becomes active.
For recursive calls, the same function gets multiple memory-space stacked one upon another. That's all. The simple idea of how stack works in memory of a computer should get you through the idea of how recursion happens in implementation.
Recursion started making sense to me when I stopped reading what others say about it or seeing it as something I can avoid and just wrote code. I found a problem with a solution and tried to duplicate the solution without looking. I only looked at the solution when I got helplessly stuck. Then I went back at trying to duplicate it. I did this again on multiple problems until I developed my own understanding and sense of how to identify a recursive problem and solve it. When I got to this level, I started making up problems and solving them. That helped me more. Sometimes, things can only be learned by trying it out on your own and struggling; until you “get it”.
Many of the answers above are very good. A useful technique for solving recursion though, is to spell out first what we want to do and code as a human would solve it . In the above case, we want to sum up a sequence of consecutive integers (using the numbers from above):
2, 3, 4, 5 //adding these numbers would sum to 14
Now, note that these lines are confusing (not wrong, but confusing).
if (a > b) {
return 0
}
Why the test a>b?, and whyreturn 0
Let's change the code to reflect more closely what a human does
func sumInts(a: Int, b: Int) -> Int {
if (a == b) {
return b // When 'a equals b' I'm at the most Right integer, return it
}
else {
return a + sumInts(a: a + 1, b: b)
}
}
Can we do it even more human like? Yes! Usually we sum up from left to right (2+3+...). But the above recursion is summing from right to left (...+4+5). Change the code to reflect it (The - can be a little intimidating, but not much)
func sumInts(a: Int, b: Int) -> Int {
if (a == b) {
return b // When I'm at the most Left integer, return it
}
else {
return sumInts(a: a, b: b - 1) + b
}
}
Some may find this function more confusing since we are starting from the 'far' end, but practicing can make it feel natural (and it is another good 'thinking' technique: Trying 'both' sides when solving a recursion). And again, the function reflects what a human (most?) does: Takes the sum of all left integers and adds the 'next' right integer.
I was having hard time to understanding recursion then i found this blog and i already seen this question so i thought i must have to share . You must read this blog i found this extremely helpful it explain with stack and even it explain how two recursion works with stack step by step. I recommend you first understand how stack works which it explain very well here : journey-to-the-stack
then now you will understand how recursion works now take a look of this post : Understand recursion step by step
Its a program :
def hello(x):
if x==1:
return "op"
else:
u=1
e=12
s=hello(x-1)
e+=1
print(s)
print(x)
u+=1
return e
hello(3)
Let me tell you with an example of Fibonacci series, Fibonacci is
t(n) = t(n - 1) + n;
if n = 0 then 1
so let see how recursion works, I just replace n in t(n) with n-1 and so on. it looks:
t(n-1) = t(n - 2) + n+1;
t(n-1) = t(n - 3) + n+1 + n;
t(n-1) = t(n - 4) + n+1 + n+2 + n;
.
.
.
t(n) = t(n-k)+ ... + (n-k-3) + (n-k-2)+ (n-k-1)+ n ;
we know if t(0)=(n-k) equals to 1 then n-k=0 so n=k we replace k with n:
t(n) = t(n-n)+ ... + (n-n+3) + (n-n+2)+ (n-n+1)+ n ;
if we omit n-n then:
t(n)= t(0)+ ... + 3+2+1+(n-1)+n;
so 3+2+1+(n-1)+n is natural number. it calculates as Σ3+2+1+(n-1)+n = n(n+1)/2 => n²+n/2
the result for fib is : O(1 + n²) = O(n²)
This the best way to understand recursive relation

Recursive method confusion

Given the below
public class Recursion {
public static int magic(int a, int b) {
if (b == 0) {
return 0;
} else {
if (b % 2 == 0)
return magic(a + a, b / 2);
else
return magic(a + a, b / 2) + a;
}
}
public static void main(String[] args) {
Recursion r = new Recursion();
System.out.println(r.magic(3,11));
//System.out.println(r.magic(2,25));
}
}
When I use r.magic(3,11) I get an output of 33 and if I use r.magic(2.25) I get an output of 50, can someone explain the math behind it to me because I can't really seem to make sense of it.
Ok, here it is.
First of all you need to know the basics of recursion like how its returns the value and what is the exit condition.
Here is the stack trace for 2 and 25. In recursion we make a stack and this is the stack for 2 and 25. The first call value of a and b is in the bottom of the stack. i.e (2,25). You need to visualize it like this only.
a b called from return magic(a+a,b/2) or return magic(a+a,b/2)+a
64 0
32 1 2
16 3 2
8 6 1
4 12 1
2 25 2
Here 1 is for calling from magic(a+a,b/2) and 2 is for calling from return magic(a+a,b/2)+a.
So while returning from the function here is stack.If it is called from 1 then it will simply return the value else it will add a with the returned value.
a b
64 0 returns 0
32 1 2 returns 32
16 3 2 returns 32+16
8 6 1 returns 32+16
4 12 1 returns 32+16
2 25 2 returns 32+16+2
So the final return statement returns 50
And for the second call similarly here is the stack trace.
a b
48 0 returns 0
24 1 2 returns 24
12 2 1 returns 24
6 5 2 returns 24+6
3 11 2 returns 24+6+3
So the final return statement returns 33
So you can see now how the result is 50 and 33.
If you have any doubt you can comment.
I guess you want some explanations, not steps of the program. Here it is:
return magic(a + a, b / 2)
is actually
return magic(2 * a, b / 2)
It means you multiply one of the numbers by 2, and divide the other one by 2. So, these operations will not change the result in Math.
ab = (2a)*(b/2)
But, you work with integers in this method. That's OK with even numbers. But, if you divide an odd number by 2, you will lose the floating part which is "0.5".
If b is odd, let's say b = 2*n+1
a*(2n+1) = (2a)((2n+1)/2)
2an + a = (2a)(n+0.5)
2an + a = 2an + a
When you work with integers, it will be that which is wrong:
2an + a = 2an
Recursively this additional a becomes 2a, 4a, ...
And you can derive a*b with summation of these multiples of a.
When b is 0, this is the end, there is no need to sum any multiples of a.

Understanding double recursion with print statement

I understand recursion when it is only called on itself once, and I sort of understand recursion when there is two, as one recursion has to finish first or something before the second can begin.
I am trying to understand the Towers of Hanoi, But what I really don't understand is the order the lines of code are read in when there is two recursions with a print statement.
Could someone break down the order simply? I have created this simple example (where test(3); )
And why does the print statement run?, isn't it invoked on itself immediately?
public static void test(int n){
if(n>0){
test(n-2);
test(n-1);
System.out.println("print " + n);
}
}
I have tried to elaborate it via diagrams. Have a look!
Lat n = 3;
Your code is not an exact implementation of TOH.
Here's the recursion tree and execution order of your code's statements (see it to believe it):
Let n = 4
4
/ \
2 3
/ \ / \
0 1 1 2
/ \ / \ / \
-1 0 -1 0 0 1
/ \
-1 0
test(4)
test(2)
test(0)
test(1)
test(-1)
test(0)
print(1)
print(2)
test(3)
test(1)
test(-1)
test(0)
print(1)
test(2)
test(0)
test(1)
test(-1)
test(0)
print(1)
print(2)
print(3)
print(4)
The function call sequence can be traced by doing a pre-order traversal of the tree. The print statements will be executed for the nodes where node-value is greater than 0, and after both the children of that node have returned.

how do recursive parameters work?

public static int exponent(int baseNum, int exp) {
if (exp == 0) return 1;
else return baseNum * exponent(baseNum, --exp);
}
I don't understand how the two parameters work in this recursive method. Is baseNum value transfered to exponent multiplied by baseNum then returned? Then the second parameter (exp) does the same until it reaches the base case?
If you could help me visualize or break down how this works that would be great! Thank you.
Here is an example call to this recursive method using 2 and 4 for the arguments~(:
exponent(2, 4)
=> 2 * exponent(2, 3)
=> 2 * exponent(2, 2)
=> 2 * exponent(2, 1)
=> 2 * exponent(2, 0) <- exp == 0, returns 1 so no more recursive calls
so working back up the chain:
2 * (1) => 2
2 * (2) => 4
2 * (4) => 8
2 * (8) => 16
A problem with this particular method is that if you were to pass in a negative value for exp on first call, you would get infinite recursion. Better to check (exp <= 0) instead
Recursive method exponent() calls itself if second argument exp is not 0, and uses returned result in further calculation. By each call, exp is decreased by 1, so finally (if initially > 0) it meets terminal condition.
A simple sequence diagram to illustrate:
exponent(2, 3)
| ----------> exponent(2, 2)
| | ----------> exponent(2, 1)
| | | ----------> exponent(2, 0)
| | | <---------- returns 1 // terminal condition
| | <---------- returns 2 * 1 = 2
| <---------- returns 2 * 2 = 4
returns 2 * 4 = 8
When you call the method the first time, say exponent(10,5) this means the recursive method gets called 5 times.
Each time exp is reduced by 1 right before calling the recursive method. The parameters are passed into the method. They are local variables, so they only exist inside the method.
exponent(10,5)
will call
else return 10 * exponent(10,4)
then
else return 10 * exponent(10,3)
then
else return 10 * exponent(10,2)
… etc
until exp ==0.
exponent() is a method for calculating a number (baseNum) to the power of another number (exp) by simply multiplying the number with itself exp number of times.
If the exponent is 0, then it will return 1 since every integer to the power of 0 equals 1 (with the exception of 0 itself, which is not covered for some reason).
Let us say that we want to calculate 2^3. We will call the method by writing exponent(2,3). What happens is the following:
return 2*exponent(2,2);
Since exponent(2,2)is the same thing as return 2*exponent(2,1);, we can instead write it as the following:
return 2*2*exponent(2,1);
exponent(2,1) is the same thing as 2*exponent(2,0) which is 2*1 (when exp is 0, we return 1). So we can instead write this as return 2*2*2*1;
So we wanted to calculate 2^3 and the method called itself three times and multiplied 2 with itself every time and finally returned the answer of 2*2*2*1.
Do not forget that 0^0 is not 1. If you call exponent(0,0) you will get 1 which is wrong.

a = (a++) * (a++) gives strange results in Java [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
I'm studying for the OCPJP exam, and so I have to understand every little strange detail of Java. This includes the order in which the pre- and post-increment operators apply to variables. The following code is giving me strange results:
int a = 3;
a = (a++) * (a++);
System.out.println(a); // 12
Shouldn't the answer be 11? Or maybe 13? But not 12!
FOLLOW UP:
What is the result of the following code?
int a = 3;
a += (a++) * (a++);
System.out.println(a);
After the first a++ a becomes 4. So you have 3 * 4 = 12.
(a becomes 5 after the 2nd a++, but that is discarded, because the assignment a = overrides it)
Your statement:
a += (a++) * (a++);
is equivalent to any of those:
a = a*a + 2*a
a = a*(a+2)
a += a*(a+1)
Use any of those instead.
a++ means 'the value of a, and a is then incremented by 1'. So when you run
(a++) * (a++)
the first a++ is evaluated first, and produces the value 3. a is then incremented by 1. The second a++ is then evaluated. a produces the value of 4, and is then incremented again (but this doesn't matter now)
So this turns into
a = 3 * 4
which equals 12.
int a = 3;
a += (a++) * (a++);
First build the syntax tree:
+=
a
*
a++
a++
To evaluate it start with the outer most element and descent recursively. For each element do:
Evaluate children from left to right
Evaluate the element itself
The += operator is special: It gets expanded to something like left = left + right, but only evaluating the expression left once. Still the left side gets evaluated to a value(and not just a variable) before the right side gets evaluated to a value.
This leads to:
Start evaluating +=
Evaluate left side of assignment to the variable a.
Evaluate the variable a to the value 3 which will be used in the addition.
Start evaluating *
Evaluate the first a++. This returns the current value of a 3 and sets a to 4
Evaluate the second a++. This returns the current value of a 4 and sets a to 5
Calculate the product: 3*4 = 12
Execute +=. The left side had been evaluated to 3 in the third step and the right side is 12. So it assigns 3+12=15 to a.
Final value of a is 15.
One thing to note here is that operator precedence has no direct influence on evaluation order. It only affects the form of the tree, and thus indirectly the order. But among siblings in the tree the evaluation is always left-to right, regardless of operator precedence.
(a++) is a post increment, so value of expression is 3.
(a++) is post increment, so value of expression is now 4.
Expression evaluation is happening from left to right.
3 * 4 = 12
Each time the you use a++, you're post-incrementing a. That means the first a++ evaluates to 3 and the second evaluates to 4. 3 * 4 = 12.
There is a general lack of understanding about how operators work. Honestly, every operator is syntactic sugar.
All you have to do is understand what is actually happening behind every operator. Assume the following:
a = b -> Operators.set(a, b) //don't forget this returns b
a + b -> Operators.add(a, b)
a - b -> Operators.subtract(a, b)
a * b -> Operators.multiply(a, b)
a / b -> Operators.divide(a, b)
Compound operators can then be rewritten using these generalizations (please ignore the return types for the sake of simplicity):
Operators.addTo(a, b) { //a += b
return Operators.set(a, Operators.add(a, b));
}
Operators.preIncrement(a) { //++a
return Operators.addTo(a, 1);
}
Operators.postIncrement(a) { //a++
Operators.set(b, a);
Operators.addTo(a, 1);
return b;
}
You can rewrite your example:
int a = 3;
a = (a++) * (a++);
as
Operators.set(a, 3)
Operators.set(a, Operators.multiply(Operators.postIncrement(a), Operators.postIncrement(a)));
Which can be split out using multiple variables:
Operators.set(a, 3)
Operators.set(b, Operators.postIncrement(a))
Operators.set(c, Operators.postIncrement(a))
Operators.set(a, Operators.multiply(b, c))
It's certainly more verbose that way, but it immediately becomes apparent that you never want to perform more than two operations on a single line.
In case of :
int a = 3;
a = (a++) * (a++);
a = 3 * a++; now a is 4 because of post increment
a = 3 * 4; now a is 5 because of second post increment
a = 12; value of 5 is overwritten with 3*4 i.e. 12
hence we get output as 12.
In case of :
a += (a++) * (a++);
a = a + (a++) * (a++);
a = 3 + (a++) * (a++); // a is 3
a = 3 + 3 * (a++); //a is 4
a = 3 + 3 * 4; //a is 5
a = 15
Main point to note here is that in this case compiler is solving from left to right and
in case of post increment, value before increment is used in calculation and as we move from left to right incremented value is used.
(a++) means return a and increment, so
(a++) * (a++) means 3 * 4
Here is the java code:
int a = 3;
a = (a++)*(a++);
Here is the bytecode:
0 iconst_3
1 istore_1 [a]
2 iload_1 [a]
3 iinc 1 1 [a]
6 iload_1 [a]
7 iinc 1 1 [a]
10 imul
11 istore_1 [a]
Here is what happens:
Pushes 3 into the stack then pops 3 from the stack and stores it at a.
Now a = 3 and the stack is empty.
0 iconst_3
1 istore_1 a
Now it pushes the value from "a" (3) into the stack, and then increments a(3 -> 4).
2 iload_1 [a]
3 iinc 1 1 [a]
So now "a" equals "4" the stack equals {3}.
Then it loads "a" again (4), pushes into the stack and increments "a".
6 iload_1 [a]
7 iinc 1 1 [a]
Now "a" equals 5 and the stack equals {4,3}
So it finally pops the fisrt two values from the stack (4 and 3), multiplies and stores it back into the stack (12).
10 imul
Now "a" equals 5 and the stack equals 12.
Finally is pops 12 from the stack and stores at a.
11 istore_1 [a]
TADA!
It is 12.
The expression starts evaluating from left. So it does:
a = (3++) * (4++);
Once the first part (3++) is evaluated, a is 4, so in the next part, it does a = 3*4 = 12.
Note that the last post-increment (4++) is executed but has no effect since a is assigned with the value 12 after this.
Example 1
int a = 3;
a = (++a) * (a++);
System.out.println(a); // 16
Example 2
int a = 3;
a = (++a) * (++a);
System.out.println(a); // 20
Just to make sure where to put ++ expression which changes the value based on the location.
Everyone has clearly explained the first expression, and why the value of a is 12.
For the follow on question, the answer is totally obvious to the casual observer:
17
Pre & post-prefix increments have a higher precedence than the multiplication operator. hence the expression is evaluated as 3*4.
If you use a++ the next time you use a it is incremented by one. So your doing
a = 3 * (3 + 1) = 3 * 4 = 12

Categories