Fibonacci summing and memoization [duplicate] - python

This question already has answers here:
Sum of Even Fibonacci Numbers < X
(5 answers)
Closed 2 years ago.
I'm taking a programming course and there's a question about fibonacci sums and recursion.
the rules are as follows:
Write a function fibsum(N) that returns the sum of all even valued fibonacci terms that are less than N.
I've gotten close I think but my summation isn't working properly, also I'd like the function to work up pretty high (like N = 10**6 at least), here's my code so far
def fibsum(n, memo = {}):
added = 0
if n<0:
return 0
if n== 1 or n == 0:
return 1
else:
if (n-1) in memo.keys():
f1 = memo[n-1]
else:
memo[n-1] = fibsum(n-1)
f1 = memo[n-1]
if (n-2) in memo.keys():
f2 = memo[n-2]
else:
memo[n-2] = fibsum(n-2)
f2 = memo[n-2]
if f1+f2 < 44:
if (f1+f2) % 2 == 0:
added += f1+f2
print ("look here",added)
return added
print (f1+f2)
return f1 + f2
I've left some print statements because I was trying to debug the problem but I've had no luck.
edit: I've been linked another question but it is done iteratively in that case, I would like to do it recursively if possible

memoization wont help you with large values for fib
but as an aside seperate your logic
def fib(n):
"""
simple recursive fibonacci function
"""
if n == 0:
return 1
return n + fib(n-1)
then make a generic memoization decorator
def memoize(fn):
cache = {}
def _tokenize(*args,**kwargs):
return str(args)+str(kwargs)
def __inner(*args,**kwargs):
token = _tokenize(*args,**kwargs)
if token not in cache:
cache[token] = fn(*args,**kwargs)
return cache[token]
now just decorate your simple recursive function
#memoize
def fib(n):
"""
simple recursive fibonacci function
"""
if n == 0:
return 1
return n + fib(n-1)
now you can make your fibsum method (and also memoize it)
#memoize
def get_fib_nums(n):
if n == 0:
return [1]
return [n] + get_fib_nums(n)
#memoize
def fibevensum(n):
return sum(n for n in get_fib_nums(n) if n%2 == 0)

Related

Dynamic Programming Scope of Variable with python for the SubSets problem

I'm learning dynamic programming. I recently found this code to compute the amount of subsets which sum is equal to a given number. But I can't understand how mem value gets updated.
def count_sets(arr,total):
mem = {}
return dp(arr,total,len(arr)-1, mem)
def dp(arr,total, i, mem):
key = str(total)+':'+str(i)
if key in mem:
return mem[key]
if total == 0:
return 1
elif total < 0 or i < 0:
return 0
elif total < arr[i]:
to_return = dp(arr,total, i-1, mem)
else:
to_return = (dp(arr,total - arr[i], i-1, mem) \
+ dp(arr,total, i-1, mem))
mem[key] = to_return
return to_return
if __name__ == "__main__":
c = count_sets([2,4,6,10],16)
print(c) # print 2
I though the first call of dp(arr,total, i, mem) in the algorthm has {} for mem.
So if I'm only returning the amount of subsets so far (also known as to_return), why is mem being update if it's not returning, shouldn't its value only live in the scope of the function?
Could someone help me better understand the scope of the variable mem? and why it gets updated? thanks!
Another Example I tried to understand was:
def add(x):
x = x+1
def main():
a = 2
add(a)
print(a)#prints 2
main()
I'll answer my own question for future readers, thanks to #Frank I found out there are either mutable ( integers, floats, strings, Booleans, and tuples) or immutable (list, dictioanry) datatypes in python.
So global list or dictionary can be changed even when it’s used inside of a function, that's why the variable mem in my code is modified through the algorithm.

Even valued terms sum in fibonacci, limit is 4 million

def fib(n):
if n<= 1:
return n
else:
return(fib(n-1)+fib(n-2))
def comp():
L=[]
for i in range(1,4000000):
if i % 2 ==0:
L.append(fib(i))
return sum(L)
print(comp())
What is wrong with this code? It does not return anything but it looks good according to me.
you should return sum(L) from function not from for loop follow below code
def fib(n):
if n<= 1:
return n
else:
return(fib(n-1)+fib(n-2))
def comp():
L=[]
for i in range(1,20):
if i % 2 ==0:
L.append(fib(i))
return sum(L)
print(comp())
and other thing look at the range its too much,because of this it will take some time or may produce any memory related error, so reduce it for testing.
The return statement is set to the wrong increment. It is executed the first time i % 2 == 0 becomes true (which is i == 2 in your case).
def fib(n):
if n<= 1:
return n
else:
return(fib(n-1)+fib(n-2))
def comp():
L=[]
for i in range(1,4000000):
if i % 2 ==0:
L.append(fib(i))
return sum(L)
print(comp())
The above code is not going to work, though. Are you aware of how big this number would get?
Try
for i in range(1,40):
as a start. It took quite a few seconds on my machine. Result is 63245985.

Unable to return in if block while calculating GCD [duplicate]

This question already has answers here:
Python recursive function returning none after completion
(3 answers)
Closed 4 years ago.
I am trying to calculate a GCD of 2 numbers, the following code block works fine, I am using recursion, but when I am trying to return a value I am not able to do so, return a results in None
def gcd(a,b):
if b == 0:
print a
return a # This is not working
else:
gcd(b,a%b)
XX = gcd(3, 5)
print (XX)
Output:
1
None
Your code
def gcd(a,b):
if b == 0:
print a
return a # This is not working
else:
gcd(b,a%b)
XX=gcd(3,5)
print (XX)
will not work, because you are missing the return statement in the line gcd(b,a%b). So it should be
def gcd(a,b):
if b == 0:
print a
return a
else:
return gcd(b,a%b)
print(gcd(12, 4))
By the way - if possible, don't code things yourself, use the predefined library:
from fractions import gcd
print(gcd(4, 12))
Your recursion will not work... you are missing a return statement and also the algorithm does not work...
This is what a recursive gcd could look like:
def gcd(a,b):
r = a % b
if r == 0:
return a
elif r == 1:
return 1
return gcd(b, r)
and here a non-recursive gcd:
def gcd(a, b):
while b:
a, b = b, a % b
return a
also note that you could just use math.gcd.

Why my using memo didn't raise the efficiency at all?

I am doing exercise in Think in Python, using Memo to calculate Fibonacci sequence is far more efficiency than not using one. But when implemented it and testing the time consumed, I find the running time is not reduced at all. I know there are certainly something wrong with my program, could someone please tell me where I went wrong. Many thanks.
import time
known = {0:0,1:1}
def fibonacci_memo(n):
"""return the nth number of fibonacci sequence
using memo to raise efficiency"""
if n in known:
return known[n]
res = fibonacci(n-1) + fibonacci(n-2)
known[n] = res
return res
def fibonacci(n):
"""return the nth number of fibonacci sequence
without using memo"""
if n == 0:
return 0
if n == 1:
return 1
return fibonacci(n-1) + fibonacci(n-2)
if __name__ == '__main__':
start = time.clock()
print fibonacci_memo(32)
elaspsed = time.clock() - start
print 'using memo time used: ' + str(elaspsed)
start = time.clock()
print fibonacci(32)
elaspsed = time.clock() - start
print 'without using memo time used: ' + str(elaspsed)
The Output is something like:
2178309
using memo time used: 1.83040345779
2178309
without using memo time used: 1.792043347
Your fibonacci_memo function isn't calling itself recursively, it's calling the original (non-memoized) fibonacci function.
The recursion of your memoized function is calling a different function. Try replacing fibonacci_memo with this:
def fibonacci_memo(n):
"""return the nth number of fibonacci sequence
using memo to raise efficiency"""
if n in known:
return known[n]
res = fibonacci_memo(n-1) + fibonacci_memo(n-2)
known[n] = res
return res

Maximum recursion, GCD(greatest common divisor)

I wrote a program to find gcd using python.
def gcd(a,b):
r=a%b
if r==0:
return a
elif r==1:
return 1
else:
gcd(a,b)==gcd(b,r)
return gcd(b,r)
Whenever I call the function it shows the message "Max. recursion exceeded." Please help
I know it can be done using looping but I want to specifically do it by using recursion method. And bear with me. I am a learner!
This statement is unnecessary and it's the one making the recursion endless: gcd(a,b)==gcd(b,r) because it's calling gcd(a,b) again and again. Just remove it:
def gcd(a,b):
r=a%b
if r==0:
return a
elif r==1:
return 1
return gcd(b,r)
Note: By the way, you got the formula wrong, you should return b on the if clause since you're dividing a/b when calculating the modulo.
def gcd(a,b):
r=a%b
if r==0:
return b
elif r==1:
return 1
return gcd(b,r)
>>>gcd(10,4)
2
If you're trying to calculate the GCD of very large numbers (e.g., when searching for common factors in RSA moduli), you might be better off avoiding recursion altogether and using an iterative function instead. For example:
def gcd(a,b):
while a:
a,b = b%a,a
return b
gcd(a,b)==gcd(b,r) doesn't do what you expect it to do.
It doesn't mean "define gcd(a,b) to be equal to gcd(b,r)".
Instead, gcd(a,b)==gcd(b,r) means:
Compute gcd(a,b)
Compute gcd(b,r)
Compare the two results and see if they're equal.
Since you're asking to compute gcd(a, b) in order to compute gcd(a, b), you'll get an endless recursion.
Instead, you want the return gcd(b, r) at that point. I.e.:
def gcd(a,b):
r=a%b
if r==0:
return a
elif r==1:
return 1
else:
return gcd(b,r)
This is how I did it
def gcd(m,n):
if m >= n:
r = m % n
if r == 0:
return n
else:
m = n
n = r
return gcd(m,n)
else:
temp = m
m = n
n = temp
return gcd(m,n)
def gcd(a,b):
if a % b == 0:
return b
return gcd(b, a % b)

Categories