Recursion function in Python - python

Consider this basic recursion in Python:
def fibonacci(number):
if number == 0: return 0
elif number == 1:
return 1
else:
return fibonacci(number-1) + fibonacci(number-2)
Which makes sense according to the (n-1) + (n-2) function of the Fibonacci series.
How does Python execute recursion that contains another recursion not within but inside the same code line? Does the 'finobacci(number-1)' complete all the recursion until it reaches '1' and then it does the same with 'fibonacci(number-2)' and add them?
For comparison, the following recursive function for raising a number 'x' into power 'y', I can understand the recursion, def power calling itself until y==0 , since there's only one recursive call in a single line. Still shouldn't all results be '1' since the last command executed is 'return 1' when y==0, therefore x is not returned?
def power(x, y):
if y == 0:
return 1
else:
return x*power(x, y-1)

Short Answer
Each time Python "sees" fibonacci() it makes another function call and doesn't progress further until it has finished that function call.
Example
So let's say it's evaluating fibonacci(4).
Once it gets to the line return fibonacci(number-1) + fibonacci(number-2), it "sees" the call fibonacci(number-1).
So now it runs fibonacci(3) - it hasn't seen fibonacci(number-2) at all yet. To run fibonacci(3), it must figure out fibonacci(2)+fibonacci(1). Again, it runs the first function it sees, which this time is fibonacci(2).
Now it finally hits a base case when fibonacci(2) is run. It evaluates fibonacci(1), which returns 1, then, for the first time, it can continue to the + fibonacci(number-2) part of a fibonacci() call. fibonacci(0) returns 0, which then lets fibonacci(2) return 1.
Now that fibonacci(3) has gotten the value returned from fibonacci(2), it can progress to evaluating fibonacci(number-2) (fibonacci(1)).
This process continues until everything has been evaluated and fibonacci(4) can return 3.
To see how the whole evaluation goes, follow the arrows in this diagram:

In the expression fibonacci(number-1) + fibonacci(number-2) the first function call will have to complete before the second function call is invoked.
So, the whole recursion stack for the first call has to be complete before the second call is started.

does the 'finobacci(number-1)' completes all the recursion until it reaches '1' and then it does the same with 'fibonacci(number-2)' and add them?
Yes, that's exactly right. In other words, the following
return fibonacci(number-1) + fibonacci(number-2)
is equivalent to
f1 = fibonacci(number-1)
f2 = fibonacci(number-2)
return f1 + f2

You can use the rcviz module to visualize recursions by simply adding a decorator to your recursive function.
Here's the visualization for your code above:
The edges are numbered by the order in which they were traversed by the execution. The edges fade from black to grey to indicate order of traversal: black edges first, grey edges last.
(I wrote the rcviz module on GitHub.)

I would really recommend that you put your code in the Python tutor.
You will the be able to get it on the fly. See the stackframe, references, etc.

You can figure this out yourself, by putting a print function in the function, and adding a depth so we can print it out prettier:
def fibonacci(number, depth = 0):
print " " * depth, number
if number == 0:
return 0
elif number == 1:
return 1
else:
return fibonacci(number-1, depth + 1) + fibonacci(number-2, depth + 1)
Calling fibonacci(5) gives us:
5
4
3
2
1
0
1
2
1
0
3
2
1
0
1
We can see that 5 calls 4, which goes to completion, and then it calls 3, which then goes to completion.

Matthew and MArtjin are right but I thought I might elaborate:
Python does stuff from left to right whenever it can. Exceptions to this rule are implied by brackets.
in x*power(x, y-1): x is evaluated then power is evaluated
While in fibonacci(number-1) + fibonacci(number-2), fibonacci(number-1) is evaluated (recursively, til it stops) and then fibonacci(number-1) is evaluated

Your second recursion functions does this (example), so 1 will not be returned.
power(2, 3)
2 * power(2, 2)
2 * 2 * power(1,2)
2 * 2 * 2 * power(0,2) # Reaching base case
2 * 2 * 2 * 1
8

def fib(x):
if x == 0 or x == 1:
return 1
else:
return fib(x-1) + fib(x-2)
print(fib(4))

def fib(n):
if n <= 1:
return n
else :
return fib(n - 1) + fib(n - 2)

Related

What is missing (while loop)?

I'm trying to sum a number like: n -> n + (n-1) + (n-2) + ... + 1. My code is working, but not doing what I wanted it to do. I would like to know if I'm missing a parameter or something like this.
def s(n):
a = n-1
r = 0
while a != 1:
r = r + a
a = a - 1
return r
print (s(10))
A good way to debug code is to try walking through its execution with a simple example.
Let's try 4. We would expect to get the answer 4+3+2+1 = 10.
s(4)
Before the loop starts, a=3, r=0.
After the first iteration,
a=2, r=3.
After the second iteration, a=1, r=5.
a != 1 is now False, so the loop ends, and we return r, which is 5. We only ever added 3 and 2 to it, and forgot to add 4 and 1.
Looking at this a level higher, your function is always missing the first (n) and the last (1) values of the sum. Fix both of these mistakes and your function should work how you expect. These are both examples of the classic fencepost error - your fence is missing posts at both ends.

Why is a factorial recursive function iterating from lowest to highest number and not from highest to lowest number?

I have this simple recursive function, which is calculating the factorial of a number. The result is good and it works like a charm.
def factorial(y):
if y == 0:
return 1
elif y == 1:
return 1
else:
result = y * factorial(y - 1)
print(result)
return result
To understand the process I've added the print(result) function to see the value of the result variable at each iteration of the recursive function.
The output is:
2
6
24
120
I was expecting this output instead :
120
24
6
2
So, why is my recursive function iterating from the lowest number to the highest and not from the highest to the lowest number ?
When result = y * factorial(y - 1) is evaluated, the multiplication can only take place when both operands are evaluated first. So first the recursive call has to be made. This means that no multiplication will take place before all recursive calls have been initiated. Only when the recursion "unwinds" and the callers get their needed operand value for it, will the multiplications be evaluated.
In other words, it is "on the way back", out of recursion that the multiplication operator is accumulating the factors (left-side operands) with the previous product (right-side operand) into a new product.
The inner-most call finishes first, so that one prints first.
The outer-most call is only ready once all the inner calls finish, so it necessarily has to be printed only after the inner calls finish.
Try this for funsies:
def factorial(y, level=0):
if y == 0:
return 1
elif y == 1:
return 1
else:
print(level*" ", "pre-call, y=", y)
result = y * factorial(y - 1, level=level+2)
print(level*" ", "post-call, result=", result)
return result
factorial(5)
Output is:
pre-call, y= 5
pre-call, y= 4
pre-call, y= 3
pre-call, y= 2
post-call, result= 2
post-call, result= 6
post-call, result= 24
post-call, result= 120
The nesting helps show the recursion level.

Finding the Maximum Pyramidal Number by recursion in Python

I'm given the task to define a function to find the largest pyramidal number. For context, this is what pyramidal numbers are:
1 = 1^2
5 = 1^2 + 2^2
14 = 1^2 + 2^2 + 3^2
And so on.
The first part of the question requires me to find iteratively the largest pyramidal number within the range of argument n. To which, I successfully did:
def largest_square_pyramidal_num(n):
total = 0
i = 0
while total <= n:
total += i**2
i += 1
if total > n:
return total - (i-1)**2
else:
return total
So far, I can catch on.
The next part of the question then requires me to define the same function, but this time recursively. That's where I was instantly stunned. For the usual recursive functions that I have worked on before, I had always operated ON the argument, but had never come across a function where the argument was the condition instead. I struggled for quite a while and ended up with a function I knew clearly would not work. But I simply could not wrap my head around how to "recurse" such function. Here's my obviously-wrong code:
def largest_square_pyramidal_num_rec(n):
m = 0
pyr_number = 0
pyr_number += m**2
def pyr_num(m):
if pyr_number >= n:
return pyr_number
else:
return pyr_num(m+1)
return pyr_number
I know this is erroneous, and I can say why, but I don't know how to correct it. Does anyone have any advice?
Edit: At the kind request of a fellow programmer, here is my logic and what I know is wrong:
Here's my logic: The process that repeats itself is the addition of square numbers to give the pyr num. Hence this is the recursive process. But this isn't what the argument is about, hence I need to redefine the recursive argument. In this case, m, and build up to a pyr num of pyr_number, to which I will compare with the condition of n. I'm used to recursion in decrements, but it doesn't make sense to me (I mean, where to start?) so I attempted to recall the function upwards.
BUT this clearly isn't right. First of all, I'm sceptical of defining the element m and pyr_num outside of the pyr_num subfunction. Next, m isn't pre-defined. Which is wrong. Lastly and most importantly, the calling of pyr_num will always call back pyr_num = 0. But I cannot figure out another way to write this logic out
Here's a recursive function to calculate the pyramid number, based on how many terms you give it.
def pyramid(terms: int) -> int:
if terms <=1:
return 1
return terms * terms + pyramid(terms - 1)
pyramid(3) # 14
If you can understand what the function does and how it works, you should be able to figure out another function that gives you the greatest pyramid less than n.
def base(n):
return rec(n, 0, 0)
def rec(n, i, tot):
if tot > n:
return tot - (i-1)**2
else:
return rec(n, i+1, tot+i**2)
print(base(NUMBER))
this output the same thing of your not-recursive function.

Time Complexity of recursive of function

Need help proving the time complexity of a recursive function.
Supposedly it's 2^n. I need to prove that this is the case.
def F(n):
if n == 0:
return 0
else:
result = 0
for i in range(n):
result += F(i)
return n*result+n`
Here's another version that does the same thing. The assignment said to use an array to store values in an attempt to reduce the time complexity so what I did was this
def F2(n,array):
if n < len(array):
answer = array[n]
elif n == 0:
answer = 0
array.append(answer)
else:
result = 0
for i in range(n):
result += F2(i,array)
answer = n*result+n
array.append(answer)
return answer
Again what I am looking for is the explanation of how to find the complexities of the two snippets of code, not interested in just knowing the answer.
All and any help greatly appreciated.
PS: for some reason, I can't get "def F2" to stay in the code block...sorry about that
Okay, the first function you wrote is an example of Exhaustive Search where you are exploring every possible branch that can be formed from a set of whole numbers up to n (which you have passed in the argument and you are using for loop for that). To explain you the time complexity I am going to consider the recursion stack as a Tree (to represent a recursive function call stack you can either use a stack or use an n-ary Tree)
Let's call you first function F1:
F1(3), now three branches will be formed for each number in the set S (set is the whole numbers up to n). I have taken n = 3, coz it will be easy for me to make the diagram for it. You can try will other larger numbers and observe the recursion call stack.
3
/| \
0 1 2 ----> the leftmost node is returns 0 coz (n==0) it's the base case
| /\
0 0 1
|
0 ----> returns 0
So here you have explored every possibility branches. If you try to write the recursive equation for the above problem then:
T(n) = 1; n is 0
= T(n-1) + T(n-2) + T(n-3) + ... + T(1); otherwise
Here,
T(n-1) = T(n-2) + T(n-3) + ... T(1).
So, T(n-1) + T(n-2) + T(n-3) + ... + T(1) = T(n-1) + T(n-1)
So, the Recursive equation becomes:
T(n) = 1; n is 0
= 2*T(n-1); otherwise
Now you can easily solve this recurrence relation (or use can use Masters theorem for the fast solution). You will get the time complexity as O(2^n).
Solving the recurrence relation:
T(n) = 2T(n-1)
= 2(2T(n-1-1) = 4T(n-2)
= 4(2T(n-3)
= 8T(n-3)
= 2^k T(n-k), for some integer `k` ----> equation 1
Now we are given the base case where n is 0, so let,
n-k = 0 , i.e. k = n;
Put k = n in equation 1,
T(n) = 2^n * T(n-n)
= 2^n * T(0)
= 2^n * 1; // as T(0) is 1
= 2^n
So, T.C = O(2^n)
So this is how you can get the time complexity for your first function. Next, if you observe the recursion Tree formed above (each node in the tree is a subproblem of the main problem), you will see that the nodes are repeating (i.e. the subproblems are repeating). So you have used a memory in your second function F2 to store the already computed value and whenever the sub-problems are occurring again (i.e. repeating subproblems) you are using the pre-computed value (this saves time for computing the sub-problems again and again). The approach is also known as Dynamic Programming.
Let's now see the second function, here you are returning answer. But, if you see your function you are building an array named as array in your program. The main time complexity goes there. Calculating its time complexity is simple because there is always just one level of recursion involved (or casually you can say no recursion involved) as every number i which is in range of number n is always going to be less than the number n, So the first if condition gets executed and control returns from there in F2. So each call can't go deeper than 2 level in the call stack.
So,
Time complexity of second function = time taken to build the array;
= 1 comparisions + 1 comparisions + 2 comparisions + ... + (n-1) comparisions
= 1 + 2 + 3 + ... + n-1
= O(n^2).
Let me give you a simple way to observe such recursions more deeply. You can print the recursion stack on the console and observe how the function calls are being made. Below I have written your code where I am printing the function calls.
Code:
def indent(n):
for i in xrange(n):
print ' '*i,
# second argument rec_cnt is just taken to print the indented function properly
def F(n, rec_cnt):
indent(rec_cnt)
print 'F(' + str(n) + ')'
if n == 0:
return 0
else:
result = 0
for i in range(n):
result += F(i, rec_cnt+1)
return n*result+n
# third argument is just taken to print the indented function properly
def F2(n, array, rec_cnt):
indent(rec_cnt)
print 'F2(' + str(n) + ')'
if n < len(array):
answer = array[n]
elif n == 0:
answer = 0
array.append(answer)
else:
result = 0
for i in range(n):
result += F2(i, array, rec_cnt+1)
answer = n*result+n
array.append(answer)
return answer
print F(4, 1)
lis = []
print F2(4, lis, 1)
Now observe the output:
F(4)
F(0)
F(1)
F(0)
F(2)
F(0)
F(1)
F(0)
F(3)
F(0)
F(1)
F(0)
F(2)
F(0)
F(1)
F(0)
96
F2(4)
F2(0)
F2(1)
F2(0)
F2(2)
F2(0)
F2(1)
F2(3)
F2(0)
F2(1)
F2(2)
96
In the first function call stack i.e. F1, you see that each call is explored up to 0, i.e. we are exploring each possible branch up to 0 (the base case), so, we call it Exhaustive Search.
In the second function call stack, you can see that the function calls are getting only two levels deep, i.e. they are using the pre-computed value to solve the repeated subproblems. Thus, it's time complexity is lesser than F1.

Python: Recursion and return statements

I have this simple code using recursion that calculates the exponent. I understand how the recursion works here except for the: if exp <= 0: return 1. Say I call the function to give me five to the second power. If I have it return 1, it will give me the correct value of 25, but if 2 it returns 50, and 3, 75.
I am having a little trouble seeing how exactly this works within the environment:
def recurPower(base,exp):
if exp <= 0:
return 1
return base*recurPower(base,exp-1)
print str(recurPower(5,2))
I'm not sure if I understand the question. The 1 in the base case is there it is base^0 (for any non-zero base) and also because it is the multiplicative identity, so you can freely multiply by it.
It might help you try "unrolling" the recursion, to see where the numbers go:
recurPower(5, 2) =
5 * recurPower(5, 1) =
5 * 5 * recurPower(5, 0) =
5 * 5 * 1 =
25
Putting 2 or 3 in place of the 1 gets you two or three times the exponent you are trying to calculate.
whats happening here, is you'll end up with a cascade of returning values that will start with the value which is returned by that return 1 statement, for example:
recurPower(5,2) ==
recurPower(5,2) -> recurPower(5,1) -> recurPower(5,0)
the return statements will then make this:
1 -> (1)*5 -> (5)*5
(in reverse of the previous chain since we're cascading up the chain).
if you change the return value to 2 you will get:
2 -> (2)*5 -> (10)*5
(in reverse of the previous chain since we're cascading up the chain).
Numbers in brackets are returned from lower down the recursion chain.

Categories