Recursive Functions in Python vs C - python

It seems as if C allows for a function to reference itself (in a recursive manner) when executing, for example, the Collatz conjecture.
int collatz(int n);
int main(void)
{
int result = collatz(9);
printf("Steps: %i\n", result);
}
int collatz(int n)
{
if (n == 1)
return 0;
else if ((n % 2) == 0)
return 1 + collatz(n / 2);
else
return 1 + collatz(3 * n + 1);
}
Python gives me an error when I try this:
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
when I reference the same function within itself:
def collatz_recursive(n):
while n != 1:
if n % 2 == 0:
return 1 + collatz_recursive(n/2)
else:
return 1 + collatz_recursive(n * 3 + 1)
However, when I place collatz in its own function and reference it from the outside with collatz_recursive I don't have that problem:
def collatz(n):
while n != 1:
if n % 2 == 0:
n = n/2
else:
n = n * 3 + 1
def collatz_recursive(n):
while n != 1:
if n % 2 == 0:
return 1 + collatz(n/2)
else:
return 1 + collatz(n * 3 + 1)

The 'int' and 'NoneType' can not be added through + operation.
Here is my console for running your very last code:
line 13, in collatz_recursive
return 1 + collatz(n * 3 + 1)
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
I think the problem is that you forgot to handle the edge-case n=1 for your collatz_recursive function, you can easily log n by putting a print function before and after while loop and observe the bug.
Try to return a default value for your function, this is also named base-case.
You can read more about recursion and base case in here

"Python gives me an error when ... I reference the same function within itself"
No, Python gives you an error because collatz_recursive doesn't return a value for n == 1. The return value of a function is None if no value was returned with a return statement.
Your Python code should look like
def collatz_recursive(n):
if n == 1:
return 0
if n % 2 == 0:
return 1 + collatz_recursive(n/2)
else:
return 1 + collatz_recursive(n * 3 + 1)

Related

python - TypeError: unsupported operand type(s) for &: 'float' and 'float' [duplicate]

This question already has answers here:
Python 3 int division operator is returning a float?
(2 answers)
Closed 6 months ago.
When I try and run my code I get the following error:
Traceback (most recent call last):
File "/home/exal/PycharmProjects/pythonProject/main.py", line 9, in <module>
if powerOfTwoCheck(n) == True:
File "/home/exal/PycharmProjects/pythonProject/main.py", line 4, in powerOfTwoCheck
return (n & (n - 1)) == 0 and n > 0
TypeError: unsupported operand type(s) for &: 'float' and 'float'
50.0
This error only occcurs when I use the % operator, everything else seems to function correctly when I remove it.
my code:
# Collatz conjecture in python
def powerOfTwoCheck(n):
return (n & (n - 1)) == 0 and n > 0
# If a number is a power of two then it will eventually lead to the 4-1 loop
n = 100
while True:
if powerOfTwoCheck(n) == True:
break
elif n%2 == 0: # checks if number is even
n = n / 2
print(n)
elif n % 2 != 0: # Checks if number is odd
n = (n * 3) + 1
print(n)
Why is it occuring and How would i fix it?
(sorry if this is formatted wrong or a bad question, I rarely use stack overflow)
It is because in this:
elif n%2 == 0: # checks if number is even
n = n / 2
it converts n into a float that give error
you have to convert it into integer
end code will be
def powerOfTwoCheck(n):
return (n & (n - 1)) == 0 and n > 0
n = 100
while True:
if powerOfTwoCheck(n) == True:
break
elif n%2 == 0:
n = int(n / 2)
print(n)
elif n % 2 != 0:
n = (n * 3) + 1
print(n)
You can use:
elif n%2 == 0:
n = int(n / 2)
or
elif n%2 == 0:
n = (n // 2)

How to write 2**n - 1 as a recursive function?

I need a function that takes n and returns 2n - 1 . It sounds simple enough, but the function has to be recursive. So far I have just 2n:
def required_steps(n):
if n == 0:
return 1
return 2 * req_steps(n-1)
The exercise states: "You can assume that the parameter n is always a positive integer and greater than 0"
2**n -1 is also 1+2+4+...+2n-1 which can made into a single recursive function (without the second one to subtract 1 from the power of 2).
Hint: 1+2*(1+2*(...))
Solution below, don't look if you want to try the hint first.
This works if n is guaranteed to be greater than zero (as was actually promised in the problem statement):
def required_steps(n):
if n == 1: # changed because we need one less going down
return 1
return 1 + 2 * required_steps(n-1)
A more robust version would handle zero and negative values too:
def required_steps(n):
if n < 0:
raise ValueError("n must be non-negative")
if n == 0:
return 0
return 1 + 2 * required_steps(n-1)
(Adding a check for non-integers is left as an exercise.)
To solve a problem with a recursive approach you would have to find out how you can define the function with a given input in terms of the same function with a different input. In this case, since f(n) = 2 * f(n - 1) + 1, you can do:
def required_steps(n):
return n and 2 * required_steps(n - 1) + 1
so that:
for i in range(5):
print(required_steps(i))
outputs:
0
1
3
7
15
You can extract the really recursive part to another function
def f(n):
return required_steps(n) - 1
Or you can set a flag and define just when to subtract
def required_steps(n, sub=True):
if n == 0: return 1
return 2 * required_steps(n-1, False) - sub
>>> print(required_steps(10))
1023
Using an additional parameter for the result, r -
def required_steps (n = 0, r = 1):
if n == 0:
return r - 1
else:
return required_steps(n - 1, r * 2)
for x in range(6):
print(f"f({x}) = {required_steps(x)}")
# f(0) = 0
# f(1) = 1
# f(2) = 3
# f(3) = 7
# f(4) = 15
# f(5) = 31
You can also write it using bitwise left shift, << -
def required_steps (n = 0, r = 1):
if n == 0:
return r - 1
else:
return required_steps(n - 1, r << 1)
The output is the same
Have a placeholder to remember original value of n and then for the very first step i.e. n == N, return 2^n-1
n = 10
# constant to hold initial value of n
N = n
def required_steps(n, N):
if n == 0:
return 1
elif n == N:
return 2 * required_steps(n-1, N) - 1
return 2 * required_steps(n-1, N)
required_steps(n, N)
One way to get the offset of "-1" is to apply it in the return from the first function call using an argument with a default value, then explicitly set the offset argument to zero during the recursive calls.
def required_steps(n, offset = -1):
if n == 0:
return 1
return offset + 2 * required_steps(n-1,0)
On top of all the awesome answers given earlier, below will show its implementation with inner functions.
def outer(n):
k=n
def p(n):
if n==1:
return 2
if n==k:
return 2*p(n-1)-1
return 2*p(n-1)
return p(n)
n=5
print(outer(n))
Basically, it is assigning a global value of n to k and recursing through it with appropriate comparisons.

How to fix "TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'"

I'm creating a program that calculates the weight on top of each person in a human pyramid, assuming each person conveniently weighs 200 pounds. My problem is the last 'elif' in my function, which brings up the error: TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'.
This needs to be a recursive function for my class.
I've tried a 'return' statement already and 'tot =' instead of 'tot +='.
tot = 0.0
def prac(r, c):
global tot
if c > r:
print('Not valid')
elif r == 0 and c >= 0:
print(tot, 'lbs')
elif r > 0 and c == 0:
tot += (200 / (2 ** r))
prac(r - 1, c)
elif r > 0 and c == r:
tot += (200 / (2 ** r))
prac(r - 1, c - 1)
elif r > 0 and r > c > 0:
tot += (200 + (prac(r - 1, c - 1)) + (prac(r - 1, c)))
prac(r == 0, c == 0)
prac(2, 1)
I expect it to calculate prac(2,1) to 300 lbs , prac(3,1) to 425, etc.
The prac function doesn't return anything, and functions that don't return are given the None type. In the last elif statement you are trying to add None to tot, which will raise the error you get.
I'm not sure what you code is trying to accomplish, so it's hard to post a correct answer, but here is a guess:
tot = 0.0
def prac(r, c):
global tot
if c > r:
print('Not valid')
elif r == 0 and c >= 0:
print(tot, 'lbs')
elif r > 0 and c == 0:
tot += (200 / (2 ** r))
prac(r - 1, c)
elif r > 0 and c == r:
tot += (200 / (2 ** r))
prac(r - 1, c - 1)
elif r > 0 and r > c > 0:
x = prac(r - 1, c - 1)
y = prac(r - 1, c)
tot += 200
if x is not None:
tot += x
if y is not None:
tot += y
prac(r == 0, c == 0)
prac(2, 1)
I went through your code and found out that you are not returning anything in your function which makes things bad in the last elif.
In each iteration, you are calling the function for further computation. Lets jump right into the last elif. Here, you are adding the values returned by the function along with the static value. Since you are not returning anything in the function, the value gets saved as NoneType. If you intend to terminate your loop at one else or elif, return the value from there. Then when you call the function in the last elif, the function will return something and the addition will proceed properly.
I don't know the mechanics but here is what I am trying to convey is make a stopping condition for the loop where it returns the value (you haven't catered the situation where C becomes less than 0 as well.
I hope you get my point. Best of luck!

Problems with modulo when calculating fibonacci

I'm trying to solve a problem that requires me to calculate Fibonacci numbers up to 10^18 mod 10^9+7. The online judge is saying that I get right answers on the small cases (where the modulo isn't required), but in larger cases I get wrong answers.
There is no problem with the algorithm otherwise, but the memoization aka saving the results into the dictionary table seems to have failed. I have no idea why.
luku = int(input())
table = {0:0, 1:1, 2:1}
def fib(num):
if num in table:
return table[num];
if num % 2 == 0:
puoli = num / 2;
ans = (fib(puoli) * (2 * (fib(puoli + 1)) - fib(puoli))) % 1000000007;
table[num] = ans;
return ans;
else:
puoli = (num-1) / 2;
ans = (fib(puoli + 1)*fib(puoli + 1) + fib(puoli)*fib(puoli)) % 1000000007;
table[num] = ans;
return ans;
print(fib(luku))
For example, with the input 54774730983471038 I'm getting 946469205 instead of the correct answer 795317107.
Nothing wrong with memorizing.
Possibly to your surprise, the problem is that floating point precision (yeah, your numbers are truncated).
You should replace floating division operator / (single slash) with integer division operator // (double).
The following code, with the only fix mentioned above, works for me:
luku = int(input())
table = {0:0, 1:1, 2:1}
def fib(num):
if num in table:
return table[num];
if num % 2 == 0:
puoli = num // 2;
ans = (fib(puoli) * (2 * (fib(puoli + 1)) - fib(puoli))) % 1000000007;
table[num] = ans;
return ans;
else:
puoli = (num-1) // 2;
ans = (fib(puoli + 1)*fib(puoli + 1) + fib(puoli)*fib(puoli)) % 1000000007;
table[num] = ans;
return ans;
print(fib(luku))
See:
ibug#ubuntu:~ $ python3 t.py
54774730983471038
795317107

TypeError: 'int' object is unsubscriptable - python,coldn't find out why?

this is my code, the purpose of the code is assume two integer and produce a list.start with a number, multiply its nonzero digits and add that product to the number. This is the new number in the sequence. Repeat.for example:Start with 12: multiply the digits (1*2) and add -> 14. Multiply its digits (1*4) and add -> 18, and so on.it will stop when it hit the limit(except the origin digit).two integers 12,5(limit) and produce a list ['12','14','18','26','38','62'] i checked many times and i don't know why i get TypeError: 'int' object is unsubscriptable. can someone trace for me? :)
def check_n(n,p,p1,old_t,new_t,fn1,t,limit):
if len(new_t) - 1 != limit:
if n != "":
if int(n[0]) != 0:
p = p*int(n[0])
t = p + fn1
return check_n(n[1:],p,p1,old_t,new_t,fn1,t,limit)
else:
return check_n(n[1:],p,p1,old_t,new_t,fn1,t,limit)
else:
pl = p1 + "," + str(t)
old_t = str(fn1) + p1
new_t = old_t.split(',')
return check_n(t,p,p1,old_t,new_t,fn1,t,limit)
else:
return new_t
def in_both_sequences(n,limit):
fn1 = n
n = str(n)
p = 1
p1 = ""
old_t = []
new_t = []
t = 0
return check_n(n,p,p1,old_t,new_t,fn1,t,limit)
In the check_n function, n must be a string. But when check_n calls itself towards the bottom
return check_n(t,p,p1,old_t,new_t,fn1,t,limit)
you pass in t, which is an integer.
I couldn't replicate the same error. But I tweaked the approach and this is gets the list you want
def check_n(base, limit):
result_list = [str(base)]
# Build the list to the limit
for x in range(0, limit):
# Pull the latest number
str_base = result_list[len(result_list) - 1]
# Multiply non-zero digits of the str_base
prod = int(str_base[0])
for y in range(1, len(str_base)):
if int(str_base[y]) != 0:
prod = prod * int(str_base[y])
prod += int(str_base)
result_list.append(str(prod))
return result_list

Categories

Resources