recursive function python 3 'maximum recursion depth exceeded' - python

I am creating a collatz sequence with a recursive function below:
def collatz(n):
if n%2 == 0:
return int(n/2)
else:
return int((3 * n)/2)
From what I understand, a recursive function is a function that basically calls itself. Below I have attempted creating the recursive function with the following:
def collatz(x):
if x == 1:
"Done"
print(x)
x = collatz(x)
return(x)
Where essentially the variable x continues to get passed into the collatz function I defined until it gets to 1. However, every time I run the recursive function it prints 'x' repeatedly and then I get the
collatz(3)
'RecursionError: maximum recursion depth exceeded in comparison'
Which I understand is an infinite loop essentially. I thought by reassigning it to x to the results of the first collatz() it would return the new value and continue till it hit '1' but I can't seem to quite get there.
Any help/tips/advice would be great! Thanks!

Recursive functions have what's known as a "base case" and what's known as a "recursive case." The base case is when you should stop recursing and return an answer.
In this case, the base case is when x==1
def collatz(x):
if x == 1:
return x
and the recursive case is the rest of the time
# continuing from above
else:
if n % 2 == 0:
return collatz(int(n//2))
else:
return collatz(n*3 / 2) # sicut. Note that the collatz sequence
# uses 3n+1 here, not 3n/2 as in the question
N.B. that I change the effective value of x in the next loop through collatz before returning the result of that new call. If you don't, and simply return collatz(x), you'll never reach your base case and recurse forever.

#Roee Gavirel
Here is the final answer based on his answer above:
def collatz(x):
if x == 1:
"Done"
elif x%2 == 0:
x = int(x/2)
print(x)
collatz(x)
else:
x = int((3*x)+1)
print(x)
collatz(x)
collatz(3)
Thanks for all the help!

You show two different implementations of the same function collatz, while you need to combine them.
def collatz(n):
if x == 1:
"Done"
print(x)
if n%2 == 0:
collatz(int(n/2))
else:
collatz(int((3 * n)/2))

Related

Why 'return' does not break a loop nested in function?

I am trying to use a loop nested in function. Why the condition is not breaking the loop with 'return' in the function and goes to to end still printing "Incremental"?
x = 1
def function(x):
if x == 4:
return print("END")
for x in range (1,8):
x += 1
print("Incremental")
if x == 4:
print("Condition met")
function(x)
function(x)
From terminal I have following output:
Incremental
Incremental
Incremental
Condition met
END
Incremental
Incremental
Incremental
Incremental
EDIT: The idead behind this task (production scheduling), was that i was iterating thorugh days of the week (1st loop - in this case n=1 means Monday) and manufactured products (2nd loop). Sometimes i need to break the first loop first, without breaking the 2nd, because i don't want to change the product, i want to change the day of the production.
The reason for this behavior is, in the code you call function(x) again when x==4. If you still want to use recursion in the code (I am not sure the reason behind it) following code will work:
x = 1
def function(x):
if x == 4:
return print("END")
for x in range (1,8):
x += 1
print("Incremental")
if x == 4:
print("Condition met")
function(x)
break
function(x)
The way you are writing your function will never do what you are expecting it to do;
When you call function inside of your loop, you are making a recursive call to the function, and since you are passing 4 to it, it returns print("END") to where you are calling it from (when you make a recursive call, you are in the context of the function you called).
TL;DR: your return statement returns from another function that gets added to the stack when you call it; So it will never break the loop.
If you wanna break there is no need to do it recursively!
this will do it
x = 1
def function(x):
for x in range (1,8):
x += 1
print("Incremental")
if x == 4:
print("Condition met")
break # or return
function(x)
You print "Incremental" 4 more times after "End" because when x == 4 you call the function(x) again inside the conditional in a a recursive manner. At x == 4 you go again into the function(x) where you print "End" and return back to the for loop and continue till the loop terminates during which "Incremental" is printed 4 more times.
An improved version of this function can be written as follows,
def function(x):
for x in range (1,8):
print("Incremental")
if x == 4:
print("Condition met")
print("End")
break
function(x)

print row prime number in recursion def python

Hi guys can u help i want to make number list prime in python but with no for loop do or while in inside or outside only with recursive function
this is mycode with def recursion, can u guys help me change to print 2-limit in def recursive ?
def is_prime(n, div=2):
if div> n/2.0: return True
if n% div == 0:
return False
else:
div+=1
return is_prime(n,div)
but this will need for outside def to print all number 2-100
#The program:
for i in range(2,100,1):
if is_prime(i):
print(i)
how to change the for in outside def, with just
limit = int(input("input limit prime = )
print(is_prime(limit,2)
what i mean is, how to print 2-limit with recursion in def without loop for,while outside def. im confuse how to make recursive function from it
Thanks
If you goal is to perform recusion on your function without an outside loop, this is a solution...
def is_prime(n, max_n, div=2):
if n> max_n: return False
if div > n / 2.0:
print(n)
return is_prime(n+1,max_n)
if n % div == 0:
return is_prime(n + 1, max_n)
else:
return is_prime(n , max_n,div+1)# forgot to increment div and not increment n so we can runit through the function again
is_prime(2, 100)

Variable location in recursion

The problem is my code keeps reflecting a variable as zero and this is caused by the fact that the variable is assigned at the start of my function, so each time I call the function the value evaluates to zero. However I need this variable assignment for the code to work and placing it within the elif statements still evaluates to zero and placing the the variable outside the function causes the function not work.
The aim of the program is to count pairs of consecutive letters in a string using recursion with no for/while loops in the code.
def countpairs(s):
pairs=0
if len(s)<2:
return 0 #base case
elif s[0].lower() == s[1].lower(): #recursion
pairs=+1
return countpairs(s[1:])
else: #recursion
pairs=+0
return countpairs(s[1:])
print(countpairs('Hello Salaam'))
This code is supposed to evaluate to 2 because of "ll" and "aa".
You need to wrap your head a little around what the recursion will do: it will call the function recursively to count the pairs from that point on, then (it should) add the pair, if any, found by this instance.
So your function needs to do something with the result of the recursive call, not just return it unchanged. For example, instead of this
elif s[0].lower() == s[1].lower():
pairs = +1
return countpairs(s[1:])
you might write this:
elif s[0].lower() == s[1].lower():
return countpairs(s[1:]) + 1
Something along these lines. You'll need to do a bit more work to get it just right, but I hope you get the idea.
The problems is that the variable pairs resets every recursive call...
When using counting recursive algorithms you don't need a variable that counts, that's the beauty
Instead, try to think how to recursive call can help you count.
def countpairs(s):
if len(s)<2:
return 0
elif s[0].lower() == s[1].lower():
return countpairs(s[1:])+1
else:
return countpairs(s[1:])
print(countpairs('Hello Salaam'))
There you go, in the recursive call the "counter" gets bigger every time it should be, think of the counter as a part of the function stack (or something like that).
You need to fix the syntax: pairs=+1 should be pairs+=1, same for pairs=+0. And you can pass the total into the next level.
def countpairs(s, pairs=0):
if len(s)<2:
return pairs #base case
elif s[0].lower() == s[1].lower(): #recursion
pairs+=1
return countpairs(s[1:], pairs)
else: #recursion
pairs+=0
return countpairs(s[1:], pairs)
print(countpairs('Hello Salaam')) # 2
You can do it by creating a recursive nested function and defining pairs in the outer function. Here's what I mean (with fixes for other issues encountered):
def countpairs(s):
pairs = 0
def _countpairs(s):
nonlocal pairs # Since it's not local nor global.
if len(s) < 2: # base case
return pairs
elif s[0].lower() == s[1].lower():
pairs += 1
return _countpairs(s[1:]) # recursion
else:
return _countpairs(s[1:]) # recursion
return _countpairs(s)
print(countpairs('Hello Salaam')) # -> 2
The code will always evaluate to zero because the last recursion will always have the length of s being less than 2. Instead use the global keyword to be able to grab the value of pairs.
numberOfPairs = 0
pairsList = []
def countpairs(s):
global numberOfPairs
if len(s)<2:
print("doing nothing")
return 0 #base case
elif s[0].lower() == s[1].lower(): #recursion
numberOfPairs+=1
newString = f"{s[0]} is equal to {s[1]}"
print(newString)
pairsList.append(newString)
return countpairs(s[1:])
else:
print(f"nothing happened: {s[0]}") #recursion
return countpairs(s[1:])
print(f"\nThe returned value of countpairs is: {countpairs('Hello Salaam')}")
print(f"Number of pairs: {numberOfPairs}")
print(pairsList)

Recursion program flow

I have some textbook code that calls itself recursively. I don't understand the program flow. Here is the code:
def Recur_Factorial_Data(DataArray):
numbers = list(DataArray)
num_counter = 0
list_of_results = []
for num_float in numbers:
n = int(num_float)
1. result = Recur_Factorial(n)
list_of_results.append(result)
def Recur_Factorial(num):
if num == 1:
2. return num
else:
result = num*Recur_Factorial(num-1)
3. return result
if num < 0:
return -1
elif num == 0:
return 0
else:
return 0
In Recur_Factorial_Data, I loop through the data elements and call Recur_Factorial, which returns its value back to the calling function (Recur_Factorial_Data). I would expect that the lines marked 2 ("return num") and 3 ("return result") would always return a value back to the calling function, but that's not the case. For example, where the initial value (from the array DataArray) is 11, the function repeatedly calls itself until num is 1; at that point, the program falls to the line marked 2, but it does not loop back to the line marked 1. Instead, it falls through to the next line. The same happened on the line marked 3 -- I would expect it to return the result back to the calling function, but it does that in some cases and not in others.
I hope this is enough description to understand my question -- I just don't know why each return does not loop back to return the result to the calling function.
EDIT: The question at Understanding how recursive functions work is very helpful, and I recommend it to anyone interested in recursion. My question here is a bit different -- I asked it in the context of the program flow of the Python code where the recursive function is called.
If it call itself recursively 10 times, it will be at the 10th level of recursion and should go back 10 times at the point where there was a recursive call with an intermediate result and only then exit from the recursive function to the place where it was called. Learn more about recursion
Also try to rearrange instructions in Recur_Factorial function in this way:
def Recur_Factorial(num):
if num < 0:
return -1
elif num == 0:
return 0
elif num == 1:
return num
else:
return num * Recur_Factorial(num-1)

Basic recursion on string?

I want to have a program that prints me a word in this way only by recursion and if-else clauses:
P
Py
Pyt
Pyth
Pytho
Python
Why does following code not work? It gives me an error of maximum recursion depth exceeded.
def oneToAll (word, x):
if -x < 0:
print(word[:-x])
oneToAll(word, x+1)
else:
return
wordOutside = "Python"
oneToAll(wordOutside, len(wordOutside))
def oneToAll (word, x):
if -x < 0:
print(word[:-x])
oneToAll(word, x-1)
elif x == 0:
print(word)
else:
return
wordOutside = "Python"
oneToAll(wordOutside, len(wordOutside))
This seems to work. Note that I've now recursed using x-1 instead of x+1 because you want x to always be working its way toward 0.
Implementing this way, you have to handle the special case where x == 0. In that case, you want to print the entire string, not word[:0] (which is always an empty string). Also note that I didn't recurse further from the 0 branch. This is because at this point, you're done. You can actually remove the else clause entirely (give it a try!).
I may be missing something, but you could achieve the same thing like this:
def one_to_all(w):
if w:
one_to_all(w[:-1])
print w
one_to_all('Python')
Your code doesn't work because (i) you add 1 to x instead of subtracting 1 and (ii) when x reaches zero, word[:-x] is an empty string, so you need to deal with that case separately.
Try this code with intuitive index of "word"
def oneToAll(word, x):
if x > 1:
print (word[0:len(word) - x])
oneToAll(word, x - 1)
elif x == 1:
print (word)
wordOutside = "Python"
oneToAll(wordOutside, len(wordOutside))

Categories