Dynamic binding using dictionaries in python? - python

I know how to do Fibonacci series recursively, that's pretty simple:
def F(n):
if n == 1 or n == 2:
return 1
else:
return k * F(n-2) + F(n - 1)
I do know however that this is extremely inefficient since it must calculate the same values again and again. A way around this is to somehow store values as you go along. Say you want the 20th value. Once you've calculated what F(13) is, its value can be stored and called directly rather than going through all the recursion levels to get the same answer.
Dictionaries are an obvious solution to this issue. However, my answer involving a dictionary does not work.
U = {1:1, 2:1}
def F(n):
global U
if n in U:
return U[n]
else:
U[n] = F(n - 2) + F(n - 1)
Once this code is run just print U[n].
I've run through the logic multiple times and everything seems fine, but I keep getting this error:
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
whenever I try a number greater than 3. I don't see how a None should ever be returned, but I concede that I may be missing some sort of nuance about dictionaries that's causing the issue.

You're missing a return statement in the else clause.
def F(n):
global U
if n in U:
return U[n]
else:
U[n] = F(n - 2) + F(n - 1)
return U[n]
Or simplified:
def F(n):
if n not in U:
U[n] = F(n - 2) + F(n - 1)
return U[n]
(global is not needed.)

Simple way using the fact that mutable defaults are only initialized once
def F(n, U={1: 1, 2: 1}):
if n not in U:
U[n] = F(n - 2) + F(n - 1)
return U[n]
This avoid having to have U in the global namespace

When n is not in U, you should also return U[n]
Just:
U = {1:1, 2:1}
def F(n):
global U
if n in U:
return U[n]
else:
U[n] = F(n - 2) + F(n - 1)
return U[n]
For the efficient:
if you want do it once, your second way is sacrifice space, and get time, I can't tell which is better in real dev environment.
if you want get the U[n] many times, store by a U is better
So if you want to store the value, maybe:
U = {1:1, 2:1}
def F(n):
for i in range(3, n+1):
U[i] = U[i - 2] + U[i - 1]
return U
fb = F(10)
print fb[3]
print fb[5]
print fb[10]

If you need to do memoization you might use functools.lru_cache (>= python 3.2). It does exactly what you want, except you don't need to modify the function and create additional data structures.
import functools
MAX_CACHE = 10**7
#functools.lru_cache(MAX_CACHE)
def F(n):
if n == 1 or n == 2:
return 1
else:
return F(n-2) + F(n - 1)
MAX_CACHE is the number of most recent calls to memorize.

Related

Writing a non-recursive function as maximum recursion depth has been exceeded

I was wondering if someone could help me rewrite this code as non-recursive so it can compute higher numbers, my current code looks like this:
def T(n):
if n < 3:
return n
return T(n - 1) + 2 * T(n - 2) - T(n - 3)
The function is designed for the purpose of arithmetic where T(0) = 0, T(1) = 1, T(2) = 2, T(3) = 4, T(5) = 7 etc...
I want to be able to compute values as high as T(1000) for example, I didn't know if there was a simplistic way to rewrite the code or if it would just be a case of computing the values?
Any help would be appreciated, I'm currently getting the error 'maximum recursion depth exceeded'
Use a "rolling" method where you keep track of the last three results and as you add the new result, you also kick the oldest:
def T(n):
if n < 3:
return n
a, b, c = 0, 1, 2
for i in range(2, n):
a, b, c = b, c, c + 2*b - a
return c
There is a decorator for caching the function values so you can use your function with no modification:
from functools import lru_cache
#lru_cache(maxsize=None)
def T(n):
if n < 3:
return n
return T(n - 1) + 2 * T(n - 2) - T(n - 3)
from python 3.9 onwards:
from functools import cache
#cache
Then you can run:
T(1000)
And will finish the execution extremely fast without any modification.
It would be better to use dynamic programming.
def t(n):
if n <3:
return n
temp = [0] * (n +1)
temp[1], temp [2] = 1,2
for i in range(3,n+1,1):
temp[i] = temp[i - 1] + 2 * temp[i - 2] - temp[i - 3]
return temp[n]

Sum of Prime using Recursion in Python

The problem given is to determine whether two numbers m and n are prime or not, and if they are, give the sum of all prime numbers from m to n. I have already made a code for the first part:
def isPrime(n, i):
if n <= i:
return True if (n == 2) else False
if n % i == 0:
return False
if i * i > n:
return True
return isPrime(n, i + 1)
However, I don't know how to do the second part of the code. A clue that our professor gave to us was to call the first function in the second part of the code, like this:
def sumOfPrime(m, n):
**enter code here**
isPrime(m, 2)
isPrime(n, 2)
I've no idea how to know all the prime numbers from m to n. Also, we are only allowed to use recursion for this problem.
I assume your professor wants you to just test all numbers between m and n for primality, then add those that pass together.
def sumOfPrime(m, n):
if isPrime(m, 2) and isPrime(n, 2):
return sum(i for i in range(m, n + 1) if isPrime(i, 2))
Here is a fully recursive version:
def sumOfPrime(m,n):
if isPrime(n,2) and isPrime(m,2):
return sumOfPrimes(m,n)
def sumOfPrimes(m, n):
if m > n:
return 0
return (m if isPrime(m,2) else 0) + sumOfPrimes(m+1,n)
If only one function, maybe better with a nestet function:
def sumOfPrime(m,n):
def helper(m,n):
if m > n:
return 0
return (m if isPrime(m,2) else 0) + sumOfPrimes(m+1,n)
if isPrime(n,2) and isPrime(m,2):
return helper(m,n)
assert sumOfPrime(2,5) == 2 +3 + 5

Getting TypeError on simple mathematical function

def num(a, t):
a = str(a)
t = str(t)
exp = int(t[len(t) - 2]) + 1
for i in range(len(a)):
stuff = sum(2 * (exp ** i))
if float(stuff % int(t)) == 0:
print("katıdır")
else:
print("katı değildir")
I'm trying to write a simple general mathematical formula that'd help me calculate whether the number t is a multiple of number a, but I get the error TypeError: 'int' object is not iterable on this line:
stuff = sum(2 * (exp ** i))
The issue probably arises from the variable exp being an integer, but I couldn't find a way to go around this.
Yes, the problem is that sum() needs a list (or iterable) and you're giving an integer to it...
I'm not sure about what you're trying to do. But if you want to know if t is a multiple of a here is a function that does that returning a boolean (True if t is a multiple of a, False otherwise) :
def num(a, t):
return t % a == 0
print(num(2, 5))
print(num(2, 4))
Output :
False
True
I just switched stuff = sum(2 * (exp ** i)) to stuff = sum([2 * (exp ** i)]), thus allowing the argument inside sum to become an iterable (thanks to #jonrsharpe for explanation).
Here's the final code:
def num(a, t):
a = str(a)
t = str(t)
exp = int(t[len(t) - 2]) + 1
for i in range(len(a)):
stuff = sum([2 * (exp ** i)])
if float(stuff % int(t)) == 0:
print("katıdır")
else:
print("katı değildir")

TypeError in Recursive Function (Decimal to Binary)

all, I have this code that, for the life of me, I can't figure out how to solve this TypeError.
def dtobr(n):
if n == 0:
return 0
else:
return (n % 2) + 10 * dtobr(int(n / 2))
I need it to return as a string (project requirement for class). The math is correct, but when I change the last line to
return str((n % 2) + 10 * dtobr(int(n / 2)))
I get
"TypeError: unsupported operand type(s) for +: 'int' and 'str'".
I have tried setting "return (n % 2) + 10 * dtobr(int(n / 2))" to x, setting y to int(x) and returning y, and I've have no clue (and Google isn't offering any solutions that I can try to apply to my problem) what else I can do. Any ideas would be helpful!!
Doing str() on the return means that all the recursive calls will also return a str, so you need to either convert those returns back to a int, e.g.:
def dtobr(n):
if n == 0:
return '0'
else:
return str((n % 2) + 10 * int(dtobr(n // 2)))
In []:
dtobr(10)
Out[]:
'1010'
Or just use a helper function to do the conversion:
def dtobr(n):
return str(dtobr_(n))
def dtobr_(n):
if n == 0:
return 0
else:
return (n % 2) + 10 * dtobr_(n // 2)
In []:
dtobr(10)
Out[]:
'1010'
But I don't see why just calling str(dtobr(10)) wouldn't be equally as good.
Note: // is integer division so you don't need to int(n/2), n//2 will do.
You can do something like:
def dtobr(n):
n = int(n)
if n == 0:
return 0
else:
return str((n % 2) + 10 * int(dtobr(int(n / 2))))
Both solutions offered so far involve conversions to str and int and back again. I don't think that's necessary and we can solve this without int() and multiplication:
def dtobr(n):
if n == 0:
return '0'
return dtobr(n // 2).lstrip('0') + str(n % 2)
The trick is to do the recursion ahead of the current digit, instead of the other way around. This avoids the conversion back to int and the multiplication by 10.
EXAMPLE
>>> dtobr(12)
'1100'
>>>

Python, square root function?

I have compiled multiple attempts at this and have failed miserably, some assistance would be greatly appreciated.
The function should have one parameter without using the print statement. Using Newton's method it must return the estimated square root as its value. Adding a for loop to update the estimate 20 times, and using the return statement to come up with the final estimate.
so far I have...
from math import *
def newton_sqrt(x):
for i in range(1, 21)
srx = 0.5 * (1 + x / 1)
return srx
This is not an assignment just practice. I have looked around on this site and found helpful ways but nothing that is descriptive enough.
This is an implementation of the Newton's method,
def newton_sqrt(val):
def f(x):
return x**2-val
def derf(x):
return 2*x
guess =val
for i in range(1, 21):
guess = guess-f(guess)/derf(guess)
#print guess
return guess
newton_sqrt(2)
See here for how it works. derf is the derivative of f.
I urge you to look at the section on Wikipedia regarding applying Newton's method to finding the square root of a number.
The process generally works like this, our function is
f(x) = x2 - a
f'(x) = 2x
where a is the number we want to find the square root of.
Therefore, our estimates will be
xn+1 = xn - (xn2 - a) / (2xn)
So, if your initial guess is x<sub>0</sub>, then our estimates are
x1 = x0 - (x02 - x) / (2x0)
x2 = x1 - (x12 - x) / (2x1)
x3 = x2 - (x22 - x) / (2x2)
...
Converting this to code, taking our initial guess to be the function argument itself, we would have something like
def newton_sqrt(a):
x = a # initial guess
for i in range(20):
x -= (x*x - a) / (2.0*x) # apply the iterative process once
return x # return 20th estimate
Here's a small demo:
>>> def newton_sqrt(a):
... x = a
... for i in range(20):
... x -= (x*x - a) / (2.0*x)
... return x
...
>>> newton_sqrt(2)
1.414213562373095
>>> 2**0.5
1.4142135623730951
>>>
>>> newton_sqrt(3)
1.7320508075688774
>>> 3**0.5
1.7320508075688772
In your code you are not updating x (and consequently srx) as you loop.
One problem is that x/1 is not going to do much and another is that since x never changes all the iterations of the loop will do the same.
Expanding on your code a bit, you could add a guess as a parameter
from math import *
def newton_sqrt(x, guess):
val = x
for i in range(1, 21):
guess = (0.5 * (guess + val / guess));
return guess
print newton_sqrt(4, 3) # Returns 2.0
You probably want something more like:
def newton_sqrt(x):
srx = 1
for i in range(1, 21):
srx = 0.5 * (srx + x/srx)
return srx
newton_sqrt(2.)
# 1.4142135623730949
This both: 1) updates the answer at each iteration, and 2) uses something much closer to the correct formula (ie, no useless division by 1).

Categories