I need to write a recursive function that takes a list L (of odd length) representing a generalized continued fraction, and returns the corresponding rational number.
The reason the list L is always odd, is the rational needs to be created by the continued fraction
L[0] + L[1]/(L[2] + L[3]/L[....]))
i've seen this as two lists a,b. Essentially in this case the a is L[even] and the b is L[odd]
My base case is when it gets down to the last 3
if n == 3: #base case
return L[0] + (L[1] / L[2])
I am not sure how to advance both the numerator and the denominator in the recursion.
I keep trying things like (GCF2R is the function) (L is the list) (n = len(L))
if n > 3:
return L[0] + (L[n-2] / GCF2R(L[0:n]))
but since the recursion is only happening in the denominator the numerator doesn't change with each recursion.
I know I am missing some fundamental step. Any help in understand much appreciated
If you look at the form of a generalized continued fraction, you can see the substructure:
L[1]
L[0] + --------------------------
L[3]
L[2] + -------------------
L[5]
L[4] + ---------------
...
Basically, a GCF is either an integer, or an expression of the form a + b/c, where a and b are integers and c is itself a GCF.
From that, the recursion follows naturally:
def GCF2R(L):
if len(L) == 1:
return L[0]
else: # Assume len(L) > 2
return L[0] + L[1]/GCF2R(L[2:])
Remove the first two elements, and recurse on the rest.
I think you want to peel these off of the end, rather than off of the front:
def GCF2R(L):
if len(L) == 1:
return L[0]
else:
return L[-2]/L[-1] + GCF2R(L[:-2])
I suppose if you passed the length, you wouldn't need to cut a new list every time:
def GCF2R(L,N):
if N == 1:
return L[0]
else:
return L[N-2]/L[N-1] + GCF2R(L,N-2)
Related
I have written a code based on the two pointer algorithm to find the sum of two squares. My problem is that I run into a memory error when running this code for an input n=55555**2 + 66666**2. I am wondering how to correct this memory error.
def sum_of_two_squares(n):
look=tuple(range(n))
i=0
j = len(look)-1
while i < j:
x = (look[i])**2 + (look[j])**2
if x == n:
return (j,i)
elif x < n:
i += 1
else:
j -= 1
return None
n=55555**2 + 66666**2
print(sum_of_two_squares(n))
The problem Im trying to solve using two pointer algorithm is:
return a tuple of two positive integers whose squares add up to n, or return None if the integer n cannot be so expressed as a sum of two squares. The returned tuple must present the larger of its two numbers first. Furthermore, if some integer can be expressed as a sum of two squares in several ways, return the breakdown that maximizes the larger number. For example, the integer 85 allows two such representations 7*7 + 6*6 and 9*9 + 2*2, of which this function must therefore return (9, 2).
You're creating a tuple of size 55555^2 + 66666^2 = 7530713581
So if each element of the tuple takes one byte, the tuple will take up 7.01 GiB.
You'll need to either reduce the size of the tuple, or possibly make each element take up less space by specifying the type of each element: I would suggest looking into Numpy for the latter.
Specifically for this problem:
Why use a tuple at all?
You create the variable look which is just a list of integers:
look=tuple(range(n)) # = (0, 1, 2, ..., n-1)
Then you reference it, but never modify it. So: look[i] == i and look[j] == j.
So you're looking up numbers in a list of numbers. Why look them up? Why not just use i in place of look[i] and remove look altogether?
As others have pointed out, there's no need to use tuples at all.
One reasonably efficient way of solving this problem is to generate a series of integer square values (0, 1, 4, 9, etc...) and test whether or not subtracting these values from n leaves you with a value that is a perfect square.
You can generate a series of perfect squares efficiently by adding successive odd numbers together: 0 (+1) → 1 (+3) → 4 (+5) → 9 (etc.)
There are also various tricks you can use to test whether or not a number is a perfect square (for example, see the answers to this question), but — in Python, at least — it seems that simply testing the value of int(n**0.5) is faster than iterative methods such as a binary search.
def integer_sqrt(n):
# If n is a perfect square, return its (integer) square
# root. Otherwise return -1
r = int(n**0.5)
if r * r == n:
return r
return -1
def sum_of_two_squares(n):
# If n can be expressed as the sum of two squared integers,
# return these integers as a tuple. Otherwise return <None>
# i: iterator variable
# x: value of i**2
# y: value we need to add to x to obtain (i+1)**2
i, x, y = 0, 0, 1
# If i**2 > n / 2, then we can stop searching
max_x = n >> 1
while x <= max_x:
r = integer_sqrt(n-x)
if r >= 0:
return (i, r)
i, x, y = i+1, x+y, y+2
return None
This returns a solution to sum_of_two_squares(55555**2 + 66666**2) in a fraction of a second.
You do not need the ranges at all, and certainly do not need to convert them into tuples. They take a ridiculous amount of space, but you only need their current elements, numbers i and j. Also, as the friendly commenter suggested, you can start with sqrt(n) to improve the performance further.
def sum_of_two_squares(n):
i = 1
j = int(n ** (1/2))
while i < j:
x = i * i + j * j
if x == n:
return j, i
if x < n:
i += 1
else:
j -= 1
Bear in mind that the problem takes a very long time to be solved. Be patient. And no, NumPy won't help. There is nothing here to vectorize.
Here is a code that finds the value of the function T given by the recurrence relation for a given value of n:
def T(n):
if n <= 0:
return 1
else:
return T(n-1) + (n-1) * T(n-2)
print T(3)
#output
2
However, the code invokes the function T twice. I have added the print statement before the second return to show this:
def T(n):
if n <= 0:
return 1
else:
print (T(n-1) + (n-1) * T(n-2))
return T(n-1) + (n-1) * T(n-2)
print T(3)
#output
1
2
1
2
Is there an efficient way of invoking the function T only once? I'm using Python 2. I'd like something short and simple, nothing too complicated.
You're going to call T 2^(n-1) times, for n >1, and there is no way to reduce that to only once without removing the recursion.
If you meant to say that you want to reduce the repetitive calls, such as T(3) calls T(2) and T(1) while T(2) also calls T(1), then you need to use a process called memoization
For example, using a dictionary of inputs to results.
seen = dict()
def T(n):
if n <= 0:
return 1
else:
if n in seen:
return seen[n]
else:
result = T(n-1) + (n-1) * T(n-2)
seen[n] = result
return result
print(T(3))
You can redefine the function from T(n) = T(n-1) + (n-1)*T(n-2) to T(n+1) = T(n) + n*T(n-1) which will allow the recursion to move forward rather than backward provided you give it the current n and previous values. By only needing the previous value instead of the two previous values, the recursive progression is easier to grasp.
def T(N,n=1,Tm=1,Tn=1): # n,Tm,Tn represent n,T(n-1),T(n)
if n>N: return Tm # stop at n=N+1 and return T(n-1)
return T(N,n+1,Tn,Tn+n*Tm)
note: the function returns a when n>N in order to cover the case where N is zero.
Actually, this could also have been written without transposing the function by moving the stop condition to N+2 instead of N+1:
def T(N,n=2,Tn_2=1,Tn_1=1): # n,Tn_2,Tn_1 represent n,T(n-2),T(n-1)
if n==N+2: return Tn_2 # stop at n=N+2 and return T(n-2)
return T(N,n+1,Tn_1,Tn_1+(n-1)*Tn_2)
which can be further simplified to:
def T(N,n=1,a=1,b=1): return T(N-1,n+1,b,a*n+b) if N else a
I have a problem for an assignment I am working on, where I have to write a recursive function in python which returns the balanced code of size k, which is defined as the list of all binary strings of length 2k that contain an equal number of 0s in each half of the string. It is only allowed to accept one parameter, k. I have so far found a way to return a list of all possible binary strings of length 2k, but am having trouble reducing the list to only those that meet the criteria. This is my code so far:
def balanced_code(k):
if k >= 0:
if k == 0:
return ['']
else:
L = []
x = balanced_code(k - 1)
for i in range(0, len(x)):
L.append('00' + x[i])
L.append('01' + x[i])
L.append('10' + x[i])
L.append('11' + x[i])
return L
else:
return
My plan was after the for loop, I would check each item in L for the criteria mentioned (number of 0s equal in each half of the string), but quickly realized that this didn't give the right result as it would reduce L during every call, and I only want to reduce it once all calls to the function have been made. Is there any way I could track what recursion level the code is on or something like that so that I only reduce the list once all calls have been made?
How recursive does this have to be? Where does the recursion need to be?
If this were me, I'd write a recursive function:
def all_strings_of_length_k_with_n_zeros(k, n):
... you should be able to write this easily as recursion
And then
def balanced_code(k):
result = []
for zeros in range(0, k + 1):
temp = all_strings_of_length_k_with_n_zeros(k, zeros)
for left, right in itertools.product(temp, temp):
result.append(left + right)
return result
It's strange that your instructor is asking you to write some code recursively that can be written straightforwardly without recursion. (The function I left as an exercise to the reader could be written using itertools.combinations).
You can approach the recursion by adding "0" and "1" bits on each side of the k-1 results. The bits need to be added last on the right side and at every position on the left side. Since this is going to produce duplicates, using a set to return the strings will ensure distinct results.
def balancedCodes(k):
if not k: return {""}
return { code[:pos]+bit+code[pos:]+bit for code in balancedCodes(k-1)
for pos in range(k)
for bit in ("0","1") }
for bc in sorted(balancedCodes(3)): print(bc)
000000
001001
001010
001100
010001
010010
010100
011011
011101
011110
100001
100010
100100
101011
101101
101110
110011
110101
110110
111111
The 111111 result is a case of having no zeroes on each side
One way to solve this recursively without creating duplicates is by using what's described by The On-Line Encyclopedia of Integer Sequences® as the "1's-counting sequence: number of 1's in binary expansion of n (or the binary weight of n)" (sequence A000120), which can be formulated as a recurrence relation (see the function, f, below). Although we could "unpack" the sequence into our result at every stage for a self-contained recursive answer, it seemed superfluous so I left the unpacking of the sequence as a separate function we can call on the result.
def str_tuple(a, b, k):
return "{0:0{align}b}{1:0{align}b}".format(a, b, align=k)
def unpack(seq, k):
bitcounts = [[] for _ in range(k + 1)]
products = []
for n, i in enumerate(seq):
for n0 in bitcounts[i]:
products.extend([str_tuple(n0, n, k), str_tuple(n, n0, k)])
products.append(str_tuple(n, n, k))
bitcounts[i].append(n)
return products
def f(n):
if n == 1:
return [0, 1]
seq_l = f(n - 1)
seq_r = list(map(lambda x: x + 1, seq_l))
return seq_l + seq_r
k = 3
print(f(k))
print(unpack(f(k), k))
Output:
[0, 1, 1, 2, 1, 2, 2, 3]
['000000', '001001', '001010', '010001', '010010',
'011011', '001100', '100001', '010100', '100010',
'100100', '011101', '101011', '101101', '011110',
'110011', '101110', '110101', '110110', '111111']
I am trying to make a program that returns the sum of all integers in a list, bigger than n or equal to n. For example,
>>>floorSum([1,3,2,5,7,1,2,8], 4)
20
Here is the code I came up with:
def floorSum(l,n):
if len(l)>0:
if l[0]<n:
floorSum(l[1:],n)
else:
s=l[0]+floorSum(l[1:],n)
return s
I am getting: UnboundLocalError: local variable 's' referenced before assignment.
Any ideas?
you forgot to initialize s to zero
def floorSum(l,n):
s = 0
if len(l) > 0:
if l[0] < n:
s = floorSum(l[1:], n)
else:
s = l[0] + floorSum(l[1:], n)
else:
return 0
return s
As others pointed out, you neglected to initialize s for all cases and check for a length of zero.
Here's an alternative approach:
def floorSum(l, n):
if len(l) > 1:
mid = len(l) // 2 # Python 3 integer division
return floorSum(l[:mid], n) + floorSum(l[mid:], n)
if len(l) == 1 and l[0] >= n:
return l[0]
return 0
This version will divide the list into halves at each step, so although it doesn't do any less work the depth of the recursion stack is O(log(len(l))) rather than O(len(l)). That will prevent stack overflow for large lists.
Another benefit of this approach is the additional storage requirements. Python is creating sublists in both versions, but in your original version the additional storage required for the sublists is (n-1) + (n-2) + ... + 1, which is O(n2). With the successive halving approach, the additional storage requirement is O(n log n), which is substantially lower for large values of n. Allocating and freeing that additional storage may even impact the run time for large n. (Note, however, that this can be avoided in both algorithms by passing the indices of the range of interest as arguments rather than creating sublists.)
Thanks I solved the problem!
Forgot to put s=0
Python is a wonderful language that allows you to do that in a single line with list comprehension.
s = sum([value for value in l if value >= n])
Another way is to use filter
s = sum(filter(lambda e: e >= n, l))
The first one basically says:
"Create a new list from the elements of l, so that they are all greater or equal to n. Sum that new list."
The second one:
"Filter only the elements that are greater or equal to n. Sum over that."
You can find ample documentation on both of these techniques.
If you found the answer useful, mark it as accepted
Okay, this question is a little strange, but I was wondering if I could do it like this.
I'm working on a simple Fibonacci number generator for fun since I was interested in programming it.
So I wrote this out:
def f(n):
if n == 1: return 1
if n == 2: return 2
else:
return f(n-1) + f(n-2)
and that ran very slowly, taking 15 seconds to do f(30) on my computer.
So then I wrote this:
def f(n):
global a
if n == 1: return 1
if n == 2: return 1
else:
if "fib(%s)" % n in a:
return a["fib(%s)" % n]
else:
z = f(n-1) + f(n-2)
a["fib(%s)" % n] = z
return z
which basically stores previous results in a dictionary like so:
{'f(1)':1,'f(2)':2,'f(3)':3,'f(4)':5} and so on. In the function it would check if that result was in that dictionary, then just use that instead of having to redo all the calculations.
This made it tons faster. I could do f(100) and it instantly appear. Going by intervals of 500, I got to f(4000) and it was still instantaneous. The one problem was that the dictionary was getting stupidly big.
So I added a = {} to the end of the function, and that didn't work; it still left a as a massive dict.
So doing this:
def f(n):
global a
if n == 1: return 1
if n == 2: return 1
else:
if "fib(%s)" % n in a:
return a["fib(%s)" % n]
else:
z = f(n-1) + f(n-2)
a["fib(%s)" % n] = z
return z
a = {}
didn't work. but if I do this:
def f(n):
global a
if n == 1: return 1
if n == 2: return 1
else:
if "fib(%s)" % n in a:
return a["fib(%s)" % n]
else:
z = f(n-1) + f(n-2)
a["fib(%s)" % n] = z
return z
# now run the function
f(100)
a = {}
a gets reset to an empty dictionary. Why does this happen and how can I fix it?
Your a = {} statement inside the function was never being executed; every possible path of execution reaches a return before then. If it WAS executed, you wouldn't have liked the results - it would have executed in every single recursive call to the function, meaning that your dictionary would never hold more than one item! You would somehow have to detect the outermost call and only clear the dict there, or (much simpler) clear it outside of the recursion as in your second example.
Note that much of the size of your dictionary is coming from the strange decision to use a long string key. Keying it with the number itself (as in a[n] = z) would make it much more compact.
(For future reference: the technique you've come up with here, of saving the results from previous function calls, is known as "memoization".)
Despite your question, what you really want is a faster way of calculating Fibonacci sequence, right? The problem with your original approach is that recurrence, despite being very elegant and quick to code, is quite slow. Fibonacci sequence has a close form solution. You should do this math directly to speed up your code.
As convention, consider the Fibonacci sequence F(i) as: F(0) = 0, F(1) = 1, F(k) = F(k-1) + F(k-2) k = 2, 3, ... The solution for this sequence is (I will not demonstrate it here, because is not the place for that) F(k) = (1/sqrt(5))*(a^k - b^k), where a = (1 + sqrt(5))/2 and b = (1 - sqrt(5))/2.
Thus, you code could be implemented like this:
def f(n):
a = (1 + 5**.5)/2
b = (1 - 5**.5)/2
F = (a**n - b**n)/5**.5
F = int(round(F)) #necessary to get an integer without the decimal part of the approximation. Afterall, you are working with irrational numbers.
return F
This code scale very well for large values of n.