Nested recursive function in python - python

I tried to implement a nested recursive function in python it is giving an error "RuntimeError: maximum recursion depth exceeded" you can see the function in the following code. your help regarding the question is appreciated.
n=10
def test(n):
if n<=0:
return 1
else:
return test(test(n-1)+1)
print test(n)

One very important part of recursion is that with every recursive call you have to get closer to your anchor case, which in this case is:
if n<=0:
return 1
However, with your code you are not getting close to this case. The problem is this line:
return test(test(n-1)+1)
Since test returns 1 when it reaches the end case and you add 1 to this result, let's see what happens when we call test(2):
The anchor case isn't executed and you go straight into the else. The you return
test(test(1)+1)
since 2-1=1. Your inner test call is also going to go to the else case and call:
test(test(0)+1)
Here your inner test call returns 1 (it has already reached the end case) which means that essentially in this line you are calling
test(2) //test(1+1)
again. Here you can see that your recursion is never ending, hence your maximum recursion depth exceeded error.
Just to clarify how you could make this code (which is obviously just an example) work:
def test(n):
if n <= 0:
return 1
else:
return test(test(n-1)-1) //notice the -1 instead of +1
Follow up question:
Why does changing the recursive call to test(test(n-2)) also result in infinite recursion?
Well this is basically because of the same reason that I pointed out right at the beginning. You need to get closer to your anchor case. While you can reach the case of n<=0 inside the nested recursive call test(n-2) you can certainly not reach it inside the outer function call.
Note that your function returns 1 when it reaches it's end case, so even if test(n-2) doesn't cause any more recursions it returns 1 (not 0), which means you end up with
test(1)
which is again going to cause an infinite loop (since you can not get n to be <= 0 for this outer function call).
You have multiple options to make the recursion work for this case: By changing your return value or by changing your anchor case. So changing the if statement to either of these will prevent an infinite recursion:
if n <= 0:
return 0
or
if n <= 1:
return 1 //you could also return any other value <= 1

Related

Simple recursion function in python

Very new to coding and especially functions. I am trying to create a recursion function that starts at n == 1, divides n by two, and then continue to divide the next number by two. The math way is fn = fn-1/2. code is as follows
def half(n):
return half(n/2)
half(1)
but i keep getting "maximum recursion depth exceeded"
help please?
You need to set a limit to recursion, you can’t display infinite
Something like when if n>0.00001: return half(n/2) else return n
You're hitting a recursion limit in Python. Your function would lead to infinite recursion if Python didn't stop at the maximum recursion depth.
You can define the function pretty much the same way as its mathematical formulation but you need some way to stop the recursion (i.e. a base case that doesn't need to recurse to get the answer).
for example, if the result for f(0) is known to be 1 then that's the base case where you can return the answer without calling the function again:
def f(n):
if n==0: return 1 # base case f(0) --> 1 (stops recursion)
else: return f(n-1)/2 # recursion fn=fn-1/2
print(f(10)) # 0.0009765625 # this happens to be 1/2^10

When to use while loops vs recursion

I am a beginner and I am beginning to learn about 'while' statement loops to perform iteration. However, earlier on I learned about 'if/else' statements and how one can perform recursion using if/else by returning a variable as well. Here's a simple countdown function using while statement:
def countdown(n):
while n > 0:
print(n)
n = n-1
print('Blast off!')
And for comparison, here is a simple countdown function using if/else and recursion.
def countdown(n):
if n > 0:
print(n)
return countdown(n-1)
elif n < 0:
return None
else:
print('Blast off!')
return
As you can see, the two functions do almost exactly the same thing, with the only difference being that the if/else statement accounts for a case where n < 0 and returns a None value, while the 'while' statement simply omits the loop and prints 'Blast off!' even if n < 0 anyway. (If there is a way to factor this in the while statement, I would love to learn, do suggest!)
My question is, seeing how the same thing can be done in if/else statements and while statements and vice versa, I would like to know a case where they are clearly differentiated and one is clearly preferable to the other. Is there a subtle conceptual difference between the two types of statements that I am missing, or are they interchangeable in usage?
They are fundamentally different. The way you have described them, both are the same thing as for loops. (I don't mean to be rude) While is used when you want something to happen as long as or until something else happens. Recursion is used for functions that are based on themselves. (common examples being factorial or the Fibonacci sequence) Often, they behave similarly in the manner you described on small scale problems. When scaled up however, both have their advantages and drawbacks.
TLDR: the functions are inherently different in how they iterate. While they each iterate, they do so based on different conditions and with different use cases.
You are actually right, the logic behind is the same and you can also apply while loop for e.g. Fibonacci sequence. Just the notation of recursion is usually shorter and more elegant.
Your code can be even simplified a bit and then you see that your solutions are kind of similar:
While loop:
def countdown(n):
while n > 0: # Step 1 -> check
print(n)
n = n-1 # Step 2 -> recursive call in while loop
print('Blast off!') # Step 3 -> end ensured by Step 1
Recursion:
def countdown(n):
if n > 0: # Step 1 -> check
print(n)
return countdown(n-1) # Step 2 -> recursive call of the countdown()
else:
print('Blast off!') # Step 3 -> end ensured by Step 1
Significant is that action n-1. You recursively act on a variable or object (Step 2) as long as your condition related to that variable/object is valid (Step 1).

How does the code prints 1 2 6 24 as output and not 24 6 2 1

def recurr(k):
if (k>0):
result =k*recurr(k-1)
print(result)
else:
result=1
return result
recurr(4)
Output:
1
2
6
24
Because you're printing result after you recurse.
When you call recurr(4), the first thing it does is call recurr(3). This calls recurr(2), then recurr(1), and finally recurr(0). This last one is the base case, so it returns 1.
After that returns, you calculate result = k * 1, which is result = 1 * 1, then it prints that, so it prints 1 and then returns 1.
Then the previous recursion calculates result = k * 1, which is result = 2 * 1, then it prints that, so it prints 2 and returns it.
This repeats through all the recursions.
Its because you were printing result everytime you called it inside function instead of print what first call of function returned.
def recurr(k):
if (k>0):
return k*recurr(k-1)
return 1
print(recurr(4)) # -> 24
Because in every call of the function recurr() the print() function is executed.
If you want to print 24 that's the code:
def recurr(k):
if (k>0):
result =k*recurr(k-1)
else:
result=1
return result
print(recurr(4))
The recursion stack will print your message multiple times. This snippet may clarify why:
def factorial(k):
if (k>0):
print(f'factorial({k}) calls factorial({k-1})')
result = k*factorial(k-1)
else:
print(f'factorial({k}) is the base case')
result=1
return result
print(factorial(4))
you have to remove the print part in your function. Instead, you should write the code like this at the end of the code:
print(recurr(4))
The point is, the function is calling itself, and each time the function is called and processes the "if" block, it throws out a print. as for the order, the function evaluates the brackets inside out. As stated by #timgeb in comments,
recurr(4) --> 4*recurr(3*recurr(2*recurr(1*recurr(0))))
This evaluates recurr(0), which then successfully evaluates recurr(1) and so on.
The recursion in your code occurs on line 3, and the print statement occurs on line 4, after the recursion. When executing recurr(4), the entire code for recurr(3) (including the print statement for recurr(3)) is executed before the print statement for recurr(4).
Get 4 friends. Label them 1!, 2!, 3! and 4!. Tell them that if asked what their value is they must ask (n-1)! for their value, and then multiply by n, write it on a bit of paper and hand to the asker. All asking, must also be done on a bit of paper.
Now ask 4! for their value, when you get it shout it out.
Next tell them to do the same but whenever they pass a bit of paper to someone, they mast also shout out the value. Record what happens.
Which of the shouters is the one to keep?
When you use recursion, you build up a set of operation on the way down to the last call. Then you unroll them from the last, backwards up out to the first.
In this toy, you build up your result from the highest number, by putting your operation (k*next_value) at the bottom, and build it up. Then you get the result of each operation, from the top to the bottom.

I need help wrapping my head around the return statement with Python and its role in this recursive statement

No this isn't homework but it is on our study guide for a test. I need to understand the role the return statement plays and the role recursion plays. I don't understand why the function doesn't break after x = 1.
def thisFunc(x):
print(x)
if x>1:
result=thisFunc(x-1)
print(result)
return x+1
Sorry, I understand how elementary this is but I could really use some help. Probably why I can't find an explanation anywhere...because it's so simple.
edit: Why does it print out what it does and what and why is the value of x at the end? sorry if I'm asking a lot I'm just frustrated
When you enter the function with a value n>1 it prints the current value, and then calls it's self with n-1. When the inner function returns it returns the value n - 1 + 1 which is just n. Hence, the function prints out the value n twice, once before the inner recursion and once after.
If n == 1, which is the base case, the function only prints 1 once and does not call it self again (and hence does not get result back to print). Instead it just returns, hence why 1 is only printed once.
Think of it like an onion.
calling thisFunc(n) will result in
n
# what ever the output (via print) of thisFunc(n-1) is
n
I don't understand why the function doesn't break after x = 1.
But it does:
>>> ================================ RESTART ================================
>>> x = 1
>>> def thisFunc(x):
print("Function called on x-value: ", x)
if x > 1:
result = thisFunc(x-1)
print(result)
return x+1
>>> thisFunc(x)
Function called on x-value: 1
2
>>>
edit: Why does it print out what it does and what and why is the value of x at the end?
Well, it prints it out because you're telling it to. Try following the value of x as you go through the function ("x is one, one is not bigger than 1; return 1+1. Ok. [new case] x is two, two is bigger than 1..." and so on).
return and recursion are part and parcel of programming; return statements designates the end of a function (even if you might have several lines more of code) and they also pass data back to whatever asked them for it. In your case you're asking "what happens when x is 1, given these rules?"; the returned data is your answer.
Recursion is simply the matter of letting the function call itself, should it (you) need to. You simply tell the program that "hey, as long as x is bigger than 1, call this function [that just so happens to be the same function initially called] on it and let it do its thing". To get a better understanding of your function I'd suggest that you add the line "Function called on x-value: " to the first print statement inside the function, or at least something that lets you identify which printed line is x and which is result.
For a more in-depth explanation on recursion, I recommend Recursion explained with the flood fill algorithm and zombies and cats

Halt a recursively called function

I'm trying to halt the for loop below once values (x,y) or (z,2) have been returned so that the value i doesn't keep increasing, and simply halts when the if or elif condition is first
def maxPalindrome(theList):
# students need to put some logic here
maxcomplist = theList[:]
maxcomplist.reverse()
control = len(theList) - 1
# exit if maxPalindrome is True
for i in range(control):
if maxcomplist[:] == theList[:]:
x = 0
y = len(theList)
return (x, y)
break
elif maxcomplist[i:control] == theList[i:control]:
successList = theList[i:control]
z = i
w = len(theList) - z - 1
return (z, w)
How can I accomplish this?
As I wrote in a comment already: that function isn't a recursive one at all.
Recursion means, that a function calls itself to complete it's purpose. This call can be indirect, meaning that the function uses helper function that will call the first function again.
But your code doesn't cover both cases.
A recursive function always have a certain architecture:
the first thing after being called should be to test, if the primitive case (or one primitive case among options) has been reached. if so, it returns.
If not it will compute whatever is needed and pass this results to itself again,
untill the primitive case is reached, and the nested function calls will finish in one after the other.
One well-known usage of recursion is the quicksort algorithm:
def quicksort(alist):
if len(alist) < 2:
return alist # primitive case: a list of size one is ordered
pivotelement = alist.pop()
# compute the 2 lists for the next recursive call
left = [element for element in alist if element < pivotelement]#left = smaller than pivotelemet
right = [element for element in alist if element >= pivotelement]#left = greater than pivotelemet
# call function recursively
return quicksort(left) + [pivotelement] + quicksort(right)
So the "stop" must be the return of a primitive case. This is vital for recursion. You cannot just break out somehow.
I don't understand the question - if I get it right, that what you want already happens. If you return, the function stops running.
Some comments in addition to this answer:
As well, I cannot see where the function is called recursively, nor what
exit if maxPalindrome is True
means. (Is this a comment, maybe?)
Besides, the maxcomplist[:]==theList[:] does not make much sense to me, and seem to be a waste of time and memory, and to have this comparison in each iteration loop doesn't make it faster as well.

Categories

Resources