I have a function that is defined in this way:
F(n) = n if n<=3
F(n) = F(n-1) + 2 * F(n-2) + 3 * F(n-3) if n>3
Now, I've written it as a recursive function and it works fine.
I'm trying to write it as an iterative function but i cant seem to make it happen.
The output should be, for example:
print(FRec(5)) => 22
print(FRec(10)) => 1657
print(FRec(15)) => 124905
Any tips?
Here is my recursive implementation:
def FRec(n):
if(n <= 3):
return n
if(n > 3):
return FRec(n - 1) + 2 * FRec(n - 2) + 3 * FRec(n - 3)
All you need is keep the last 3 results:
from collections import deque
def F_iter(n):
if n <= 3:
return n
prev = deque([1, 2, 3], maxlen=3)
for i in range(4, n + 1):
result = prev[-1] + 2 * prev[-2] + 3 * prev[-3]
prev.append(result)
return prev[-1]
If a deque is not 'available' to you, then you can inefficiently replace that with some list slicing and concatenation:
prev = [1, 2, 3]
for i in range(4, n + 1):
result = prev[-1] + 2 * prev[-2] + 3 * prev[-3]
prev = prev[1:] + [result]
Demo:
>>> F_iter(5)
22
>>> F_iter(10)
1657
>>> F_iter(15)
124905
Related
Calculate the n member of the sequence given by the formulas
a[2 * n] = a[n] + 1
a[2 * n + 2] = a[2 * n + 1] - a[n]
a[0] = a[1] = 1
n > 0
I've tried a lot of variants, but I can't find correct one.
n = int(input())
a = [0 for i in range(n + 3)]
a[0] = a[1] = 1
i = 1
while i * 2 + 2 < n + 3:
a[2 * i] = a[i] + 1;
a[2 * i + 1] = a[2 * i + 2] + a[i]
a[2 * i + 2] = a[2 * i + 1] - a[i]
i += 1
print(a[n])
We should first compute the expected output for the first few numbers to let us have an idea what the sequence is like first,
a[0] = a[1] = 1
Substitute n = 1 in the first recurrence relation gives
a[2] = a[1] + 1 = 2
Substitute n = 1 in the second recurrence relation gives
a[4] = a[3] - a[1]
But a[4] = a[2] + 1 = 3 according to the first recurrence relation, so 3 = a[3] - 1, which gives a[3] = 4
We have a = {1, 1, 2, 4, 3, ... }
Your program gives a = {1, 1, 2, 1, 3, ...}
What went wrong in your program?
We notice that when i = 1, the line a[2 * i + 1] = a[2 * i + 2] + a[i] evaluates to a[3] = a[4] + a[1]. However, at that time, a[4] is not evaluated yet, causing an incorrect output.
The issue, therefore, lies in how you order your statements in the while loop. Make sure that statements in your loop only make use of values that will not be changed later.
How should we do that?
if we manipulate the second recurrence relation as follows:
a[2 * i + 2] = a[2 * i + 1] - a[i]
a[2 * i + 1] = a[2 * (i + 1)] + a[i]
Using the first recurrence relation, we have
a[2 * i + 1] = a[i + 1] + 1 + a[i]
which should resolve the issue since 2 * n + 1 > n + 1 for all positive n.
After modifying the second statement, you check that every element in a is computed and you should be done.
Note
One more thing to note is that the third statement is redundant since the first statement covers all even elements in a already.
In fact, a more efficient approach, in particular a logarithmic solution exist2 if you only have to calculated the nth member of the sequence.
I found decision
n = int(input())
k = n if n % 2 == 0 else n + 1
a = [None for i in range(k + 1)]
a[0] = a[1] = 1
def fill_list(a):
while None in a:
i = 1
while i * 2 <= k:
if a[i] != None:
a[2 * i] = a[i] + 1
i += 1
i = 1
while i * 2 + 2 <= k:
if a[i * 2 + 2] != None and a[i] != None:
a[i * 2 + 1] = a[i * 2 + 2] + a[i]
i += 1
fill_list(a)
print(a[n])
Your second formula gives a[2n+2] = a[2n+1] - a[n]. That can be rewritten: a[2n+1] = a[2n+2] + a[n] which is a[n+1] + a[n] + 1 from the first formula.
We can use this to write a simple dynamic programming algorithm that runs in linear time:
def A(n):
a = [1] * (n+1)
for i in range(2, n+1):
if i%2 == 0:
a[i] = a[i//2] + 1
else:
a[i] = a[i//2] + a[i//2+1] + 1
return a[n]
However, we can note that we can solve this in logarithmic time, by noting that we can compute both a[n] and a[n+1] from a[n//2] and a[n//2+1].
If n is even, then a[n]=a[n//2]+1 and a[n+1]=a[n//2]+a[n//2+1]+1.
And if n is odd, then a[n]=a[n//2]+a[n//2+1]+1 and a[n+1]=a[n//2+1]+1.
These are just applications of the formulas we have already.
This gives us this solution:
def A2(n):
if n == 0:
return 1, 1
if n == 1:
return 1, 2
a, b = A2(n//2)
if n % 2 == 0:
return a+1, a+b+1
else:
return a+b+1, b+1
Note that this returns 2 values, but for all n, A(n) == A2(n)[0].
I'm trying to calculate the nth term but its giving me wrong answers
import math
def bernoulli(m):
if m == 0:
return 1
else:
t = 0
for k in range(0, m):
t += math.comb(m, k) * bernoulli(k) / (m - k + 1)
return 1 - t
def pn(n, x):
sum = 0
for i in range(n):
sum += ((bernoulli(2 * i)) / math.factorial(2 * i)) * (-4**i) * (1 - (4**i)) * (x**((2 * i) - 1))
Equation:
Here are a few comments:
In python, the convention is to include the start, and exclude the end. list(range(1,4)) is only [1, 2, 3], not [1,2,3,4]. Thus your Bernouilli loop should be for k in range(0, m+1) and your pn loop should be for i in range(1, n+1).
Exponentiation has a higher precedence than most operators. -4**i is parsed as -(4**i), not as (-4)**i.
sum is already the name of a builtin function in python. It is very strongly advised not to shadow the names of builtins. Call that variable s or total or something else, not sum.
Finally, the code becomes:
import math
def bernoulli(m):
if m == 0:
return 1
else:
t = 0
for k in range(0, m+1):
t += math.comb(m, k) * bernoulli(k) / (m - k + 1)
return 1 - t
def pn(n, x):
s = 0
for i in range(1, n+1):
s += ((bernoulli(2 * i)) / math.factorial(2 * i)) * ((-4)**i) * (1 - (4**i)) * (x**(2 * i - 1))
return s
And, using builtin function sum:
import math
def bernoulli(m):
if m == 0:
return 1
else:
return 1 - sum(math.comb(m, k) * bernoulli(k) / (m - k + 1)
for k in range(0, m+1))
def pn(n, x):
return sum((bernoulli(2 * i)) / math.factorial(2 * i)) * ((-4)**i) * (1 - (4**i)) * (x**(2 * i - 1)
for i in range(1, n+1))
Why is it O(n^6)? and not O(n^9)?
def fa1(n):
k = 0
for i in range(1, (n ** 6) + 1) :
for j in range(i * 3, (n ** 3) + 1):
k += 1
Thanks.
First of all, a computation that is O(n^6) is also O(n^9) (n >= 0), by defintion of the big O notation. The latter is just a poorer approximation.
Second, it's trivial if you rewrite your function like this:
def fa1(n):
k = 0
for i in range(1, ((n ** 3) + 1)//3 + 1) :
for j in range(i * 3, (n ** 3) + 1):
k += 1
for i in range(((n ** 3) + 1)//3 + 1, (n ** 6) + 1) :
for j in range(i * 3, (n ** 3) + 1):
k += 1
The second loop has always i * 3 >= (n ** 3) + 1, hence the inner loop is skipped because the range is empty. The function is thus equivalent to:
def fa1(n):
k = 0
for i in range(1, ((n ** 3) + 1)//3 + 1) :
for j in range(i * 3, (n ** 3) + 1):
k += 1
That is obviously O(n^6) and even θ(n^6) (big Theta).
You can compute k more directly but I guess k += 1 is just a placeholder here.
I'm trying to translate a loop to a recursive algorithm. Fairly simple, I've just hadn't been able to make it ignore the n value when summing up the values, like range does.
This is the iterative function:
def function(n):
total=0
for i in range(1,n,2):
total += i
print(total)
function(5) # Output: 4
This is the recursive I've tried:
def function1(n):
if n==1:
return n
else:
return n+function1(n-2)
function(5) # Output: 9
So function1 does sum the n when it should be ignored. Cause range() does not include the stop number.
Then, I tried:
def f1(n):
def f_recursive(n):
if n==1 or n==2:
return 1
elif n==0:
return 0
else:
return n + f_recursive(n - 2)
return f_recursive(n) - n
print(f1(5)) # Output: 4 Yeiii!!
But then I realised, that only works for odd numbers. Not for even. If f1(6) then you get 4 when it should be 9, because it ends up being 11-6= 9.
So silly me I tried:
def f1(n):
def f_recursive(n):
if n==1 or n==2:
return 1
elif n==0:
return 0
elif n%2 == 0:
return n + f_recursive(n - 3)
elif n%2 == 1:
return n + f_recursive(n - 2)
return f_recursive(n) - n
print(f1(6))
Which of course also did not work. Am I not understanding recursion properly here?
The tricky part is excluding the upper bound. If the upper bound is your only parameter n, you have to know when it's the first call, and when it's an intermediate (recursive) call. Alternatively, if inner functions are okay, you could instead just count from 1 up until you hit n:
def function1(n):
def inner(i):
return 0 if i >= n else i + inner(i + 2)
return inner(1)
You want to compute the sum of all odd integers from 1 up to, but not including, n.
This leaves 2 possibilities:
If n is <= 1, there are no numbers to sum, so the sum is 0.
The highest number that might be included in the list is n-1, but only if it is odd. Either way, the rest of the sum is "the sum of all odd integers from 1 up to, but not including, n-1" (sound familiar?)
This translates to:
def f1(n):
if n <= 1:
return 0
else:
isOdd = (n-1)%2==1
return f1(n-1) + (n-1 if isOdd else 0)
The problem with your recursion is that you're returning n rather than the value in the range (list) that you're currently on, this poses a problem since n is not inclusive within the range and should not be added to the final total
Ideally you need to reverse the logic and traverse it the same way your range does
def func(start,end, step):
if(start >= end):
return 0
return start + func(start + step, end, step)
You just have to recognize the three types of ranges you might be adding up.
range(1, n, 2) where n <= 1: The empty range, so the sum is 0
range(1, n, 2) where n > 1 and n is even: the range is 1, ..., n-1. (E.g. range(1, 6, 2) == [1, 3, 5])
range(1, n, 2) where n > 1 and n is odd: the range is 1, ..., n-2 (E.g., range(1, 5, 2) == [1, 3]
Translating this to code is straightforward:
def f_recursive1(n):
if n <= 1:
return 0
elif n % 2 == 0:
return n - 1 + f_recursive1(n-2)
else: # n odd
return n - 2 + f_recursive1(n-2)
However, this does more work than is strictly necessary, since subtracting 2 from n will never change its parity; you don't need to check n is even or odd in every recursive call.
def f_recursive2(n):
def f_helper(x):
if x <= 0:
return 0
return x + f_helper(x-2)
if n % 2 == 0:
return f_helper(n-1)
else:
return f_helper(n-2)
If we are allowed multiplication and division, I hope you realise that this particular task does not require more than just a base case.
Python code:
def f(n):
total=0
for i in range(1,n,2):
total += i
return total
def g(n):
half = n // 2
return half * half
for n in xrange(100):
print f(n), g(n)
Since
*
* * *
* * * * *
* * * * * * *
can be seen as nested, folded rows. Here are the top two folded rows:
*
* * *
* * * *
* * * *
Let's rotate counterclockwise 45 degrees
* * * *
* * * *
* *
* *
and add the other two folded rows,
*
* *
* * * *
* * * *
* * * *
* * *
and
*
to get
* * * *
* * * *
* * * *
* * * *
the area of a square.
I have the functions:
h(0) = 0
h(1) = 3
h(n) = h(n-1) + 2 * h(n-2), for n>= 2
I need to convert this into a for loop, while loop, and recursive function. I have the recursive function figured out, but I can't seem to output the correct answer. My attempt at the for loop is this:
def hForLoop(n):
sum = 3
for i in range(2, n):
sum = sum + ((i - 1) + 2 * (i - 2))
return sum
I can't seem to figure out why I'm outputting the wrong answer. Some insight would be very useful and I will be very grateful.
Here's the version that stores just the last two values in a series:
def hForLoop(n):
prev, cur = 0, 3
for i in range(2, n + 1):
cur, prev = cur + prev * 2, cur
return cur
The issue is in you for-loop, where you increment sum with ((i - 1) + 2 * (i - 2)).
If you understood the original functions, it should really be increment sum with the previously computed value stored at h(i-1) and h(i-2).
Here's my fix to your for-loop function:
def hForLoop(n):
sum = [0,3]
for i in range(2, n+1):
sum.append((sum[i - 1]) + 2 * (sum[i - 2]))
return sum[n]
You need to store the intermediate values for h(n-1) and h(n-2) for the next iteration of the loop, where you use the values to calculate the next h(n).
def hLoop(n):
# initally [h(2), h(1), h(0)]
h = [3, 3, 0]
# And in the following: [ h(i), h(i-1), h(i-2)]
for i in range(2, n + 1):
# calculate h(i)
h[0] = h[1] + 2 * h[2]
# move 'index' forward, h(n-1) becomes h(n-2), h(n-1) becomes h(n-0)
h[2] = h[1]
h[1] = h[0]
return h[0]
With original function:
h(0) = 0
h(1) = 3
h(n) = h(n-1) + 2 * h(n-2), for n>= 2
you actual code is:
h(0) = 0
h(1) = 3
h(n) = Σ((n-1) + 2 * (n-2)), for n>= 2
See the difference?