Python, recursions in range(a,b) - python

I am trying to finish 1 exercise but i cannot find a solution myself.
I get a number and function should use recursion to find a value:
if n == 1: return 1
elif n != 1: fun(n-1) + n
but i want to provide to my function 2 values, starting point and finishing point and my function finds all values in range(starting point, finishing point).

Define your function with two parameters. One of them gets idecremented when you make the recursive call, the other is kept the same:
def sumRange(start, end):
if start > end:
return None # or could signal an error
elif start == end:
return start
else:
return sumRange(start, end-1) + end
Don't forget that when you make the recursive call, you have to return the result.

Related

Understanding the code behind a gridtraveller

I found a basic code in python to find the numbers of paths you can take in a (m,n) grid if you can only go either down or right.
def gridtraveller(m,n):
if m == 0 or n == 0:
return 0
elif m == 1 or n == 1:
return 1
return gridtraveller(m-1,n) + gridtraveller(m,n-1)
But I dont understand why is this working for two thing:
What does def something (m,n) do ?
And why does here we return the definition ? ( I do understand why we return
m-1 and n-1 , but I don't understant the concepte of a def returning a def)
Thanks to you and sorry english is not my first language.
In Python the def keyword is simply used to define a function, in this case it's the function gridtraveller(m,n). What you're seeing with that last return statement is actually a function returning the value of another function. In this case it's returning the value of another call to gridtraveller, but with different parameter values; this is called recursion. An important part of recursion is having appropriate base cases, or return values that won't end in another recursive call(i.e. the return 0 or return 1 you see).
It can be easier to understand by simply stepping through a few iterations of the recursive calls. If your first function call starts with m = 2 and n = 1, the first call will end with return gridtraveller(1,1) + gridtraveller(2,0). The first call in that statement will then return 1 since either m or n are 1 and the second returns 0 since n = 0 here giving a total result of 1. If larger values of m and n are used it will obviously result in a higher number since more calls to gridtraver(m,n) will happen.

Recursion / Recursion Trace

I'm trying to see the recursion trace of this function but why do i get "None" output?
def fnc(k):
if k == 0:
return 0
fnc(k-1)
fnc(k-1)
fnc(k-1)
fnc(k-1)
Your problem here is actually pretty easily identified by evaluating your code by hand for small parameters. Let's say you pass k = 1 to fnc:
def fnc(k):
# k == 1 != 0, so we skip the return
if k == 0:
return 0
# Now we call fnc four times with k - 1 = 0 as an argument
# All four function calls will return 0
# But we don't use the returned value in any way (no assignment, no return)
fnc(k - 1)
fnc(k - 1)
fnc(k - 1)
fnc(k - 1)
# The function ends without returning anything, therefore the return value is None
I don't know what you're trying to achieve, but if you want the base case value returned, this will do:
def fnc(k):
if k == 0:
return 0
return fnc(k-1)
Please compare these two functions, maybe step through it by hand and try to understand what exactly is going on.

How does this while-loop compute? (x = function(x))

I'm doing a quiz from "Automate the Boring Stuff with Python", and after tinkering with the problem for a bit, I finally found a solution that worked (with a little help from a comp-sci buddy of mine). The quiz asks me to make program that executes a Collatz-sequence.
I understand the logic behind all of the code, EXCEPT for the final line.
Here's my code with a few comments:
def collatz(number):
if number % 2 == 0:
print(number // 2)
return number // 2
elif number % 2 == 1:
print(3 * number + 1)
return 3 * number + 1
guess = input("Your guess please ")
while guess != 1:
guess = collatz(int(guess))
The output of the program is a sequence of numbers, as the while-loop somehow re-iterates over the returned value of the function, and uses that for another computation.
My problem is with the last line. Here's how I understand it:
Once I enter the while-loop, my function "collatz" is called, using my input-value
The function is run, and my input is computed, and based on the input, I get either the even or odd calculation in return
Here's where my brain hurts!
Is the line "guess = collatz(...)" now constantly updating "guess" to be equal to the retuned value from the function? If this is the case, then I completely understand the flow. If it's not the case, then I don't understand how the returned value is constantly being used for new calculations.
Also, is this what is called "recursion"?
Short answer:
Yes.
Longer answer: (still short)
The collatz function is returning a value which is assigned to guess.
Also, this is not called recursion, recursion is a function which calls itself.
First, no, this is not a recursion. Recursion is a function that calls itself.
For instance this is a recursion:
def fibonacci(n):
if n == 0:
return 0
if n == 1:
return 1
return fibonacci(n-1) + fibonacci(n-2)
As you can see here fibonacci function will call fibonacci function ... But it also has an exit condition (n == 0, and n == 1). Without that, this would cause runtime error with message that maximum recursion depth exceeded. But if I am not mistaken, you can check what is the maximum depth of recursion with following command:
import sys
print(sys.getrecursionlimit())
On my computer, this number is 1000. If this number is to small for you, you can also set it with this command:
sys.setrecursionlimit(n)
About other thing. Your function is returning some calculated value and in your main loop, this is assigned to variable guess. So everytime, that main loop will go through, value of guess will also update

Finding multiples using recursion

Given 1 to 100 numbers, for multiples of 3 it should print "he" ,for multiples of 5 it should print "llo" ,for both multiples of 3 and 5 it should print "hello".
This is what I have:
for i in range (1,100):
if(i%3==0):
print("he")
elif(i%5==0):
print("llo")
elif(i%3==0 and i%5==0):
print("hello")
How would I do this recursively?
How about the code below?
def find_multiples(current, last_num=100):
# Base Case
if current > last_num:
return
result = ""
if current % 3 == 0:
result += "he"
if current % 5 == 0:
result += "llo"
if result:
print(f"{current}: {result}")
find_multiples(current+1, last_num)
find_multiples(1)
Base case is if current reaches last_num or the maximum number you'd like to check.
Here is a general outline for doing simple recursive things in python:
BASE_CASE = 1 #TODO
def f(current_case):
if current_case == BASE_CASE:
return #TODO: program logic here
new_case = current_case - 2 #TODO: program logic here ("decrement" the current_case somehow)
#TODO: even more program logic here
return f(new_case) + 1 #TODO: program logic here
Of course, this doesn't handle all possible recursive programs. However, it fits your case, and many others. You would call f(100), 100 would be current_value, you check to see if you've gotten to the bottom yet, and if so, return the appropriate value up the call stack. If not, you create a new case, which, in your case, is the "decrement" logic normally handled by the "loop" construct. You then do things for the current case, and then call the function again on the new case. This repeated function calling is what makes it "recursive". If you don't have an "if then" at the beginning of the function to handle the base case, and somewhere in the function recall the function on a "smaller" value, you're probably going to have a bad time with recursion.
This recursive function prints multiples of a number! hope it helps
def multi(n,x):
if x == 12:
print(n*x)
else :
print(n*x,end =",")
multi(n,x+1)
print(multi(4,1));

Variable Scope Issue in Python

I am new to Python and I have been working with it for a bit, but I am stuck on a problem. Here is my code:
def collatz(num,ctr):
if(num != 1):
ctr+=1
if(num%2==0):
collatz(num/2,ctr)
else:
collatz(num*3+1,ctr)
return ctr
test=collatz(9,0)
For any number I put in for num, let's say 9 for instance, and 0 for ctr, ctr always comes out as 1. Am I using the ctr variable wrong?
EDIT:
I am trying to print out how many times the function is recursed. So ctr would be a counter for each recursion.
The variable ctr in your example will always be 1 because of the order of the recursive call stack. As one value of ctr is returned, then the call stack will start returning the previous values of ctr. Basically, at the very last recursive call, the highest value of ctr will be returned. But since the method call at the bottom of the call stack returns the very last value aka the value that will be stored in test, test will always be 1. Let's say I input parameters into collatz that would result in five total calls of the method. The call stack would look like this coming down,
collatz returns ctr --> 5
collatz returns ctr --> 4
collatz returns ctr --> 3
collatz returns ctr --> 2
collatz returns ctr --> 1 //what matters because ctr is being returned with every method call
As you can see, no matter how many times collatz is called, 1 will always be returned because the call at the bottom of the call stack has ctr equaling 1.
The solution can be a lot of things, but it really depends on the purpose of what you're trying to accomplish which isn't clearly stated in your question.
EDIT: If you want ctr to end up being the number of times a recursive call is made, then just assign ctr to the value of the method call. It should look like this,
def collatz(num,ctr):
if(num != 1):
ctr+=1
if(num%2==0):
ctr = collatz(num/2,ctr)
else:
ttr = collatz(num*3+1,ctr)
return ctr
test=collatz(9,0)
I changed your recursive calls to set the value received back from the recursive calls into ctr. The way you wrote it, you were discarding the values you got back from recursing.
def collatz(num,ctr):
if(num != 1):
ctr+=1
if(num%2==0):
ctr=collatz(num/2,ctr)
else:
ctr=collatz(num*3+1,ctr)
return ctr
test=collatz(9,0)
An example:
def collatz(number):
if number % 2 == 0:
print(number // 2)
return number // 2
elif number % 2 == 1:
result = 3 * number + 1
print(result)
return result
n = input("Give me a number: ")
while n != 1:
n = collatz(int(n))
Function parameters in Python are passed by value, not by reference. If you pass a number to a function, the function receives a copy of that number. If the function modifies its parameter, that change will not be visible outside the function:
def foo(y):
y += 1
print("y=", y) # prints 11
x = 10
foo(x)
print("x=", x) # Still 10
In your case, the most direct fix is to make ctr into a global variable. Its very ugly because you need to reset the global back to 0 if you want to call the collatz function again but I'm showing this alternative just to show that your logic is correct except for the pass-by-reference bit. (Note that the collatz function doesn't return anything now, the answer is in the global variable).
ctr = 0
def collatz(num):
global ctr
if(num != 1):
ctr+=1
if(num%2==0):
collatz(num/2)
else:
collatz(num*3+1)
ctr = 0
collatz(9)
print(ctr)
Since Python doesn't have tail-call-optimization, your current recursive code will crash with a stack overflow if the collatz sequence is longer than 1000 steps (this is Pythons default stack limit). You can avoid this problem by using a loop instead of recursion. This also lets use get rid of that troublesome global variable. The final result is a bit more idiomatic Python, in my opinion:
def collats(num):
ctr = 0
while num != 1:
ctr += 1
if num % 2 == 0:
num = num/2
else:
num = 3*num + 1
return ctr
print(collatz(9))
If you want to stick with using recursive functions, its usually cleaner to avoid using mutable assignment like you are trying to do. Instead of functions being "subroutines" that modify state, make them into something closer to mathematical functions, which receive a value and return a result that depends only on the inputs. It can be much easier to reason about recursion if you do this. I will leave this as an exercise but the typical "skeleton" of a recursive function is to have an if statement that checks for the base case and the recursive cases:
def collatz(n):
if n == 1:
return 0
else if n % 2 == 0:
# tip: something involving collatz(n/2)
return #???
else:
# tip: something involving collatz(3*n+1)
return #???
The variable will return the final number of the collatz sequence starting from whatever number you put in. The collatz conjecture says this will always be 1

Categories

Resources