Write an algorithm for the sequence - python

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].

Related

I need help doing this double summation in python

I'm pretty new in python and I'm having trouble doing this double summation.
I already tried using
x = sum(sum((math.pow(j, 2) * (k+1)) for k in range(1, M-1)) for j in range(N))
and using 2 for loops but nothing seens to work
You were pretty close:
N = int(input("N: "))
M = int(input("M: "))
x = sum(sum(j ** 2 * (k + 1) for k in range(M)) for j in range(1, N + 1))
It also can be done with nested for loops:
x = 0
for j in range(1, N + 1): # [1, N]
for k in range(M): # [0, M - 1]
x += j ** 2 * (k + 1)
After a little math...
x = M * (M+1) * N * (N+1) * (2*N+1) // 12

Pythagorean Triplet with given sum

The following code prints the pythagorean triplet if it is equal to the input, but the problem is that it takes a long time for large numbers like 90,000 to answer.
What can I do to optimize the following code?
1 ≤ n ≤ 90 000
def pythagoreanTriplet(n):
# Considering triplets in
# sorted order. The value
# of first element in sorted
# triplet can be at-most n/3.
for i in range(1, int(n / 3) + 1):
# The value of second element
# must be less than equal to n/2
for j in range(i + 1,
int(n / 2) + 1):
k = n - i - j
if (i * i + j * j == k * k):
print(i, ", ", j, ", ",
k, sep="")
return
print("Impossible")
# Driver Code
vorodi = int(input())
pythagoreanTriplet(vorodi)
Your source code does a brute force search for a solution so it's slow.
Faster Code
def solve_pythagorean_triplets(n):
" Solves for triplets whose sum equals n "
solutions = []
for a in range(1, n):
denom = 2*(n-a)
num = 2*a**2 + n**2 - 2*n*a
if denom > 0 and num % denom == 0:
c = num // denom
b = n - a - c
if b > a:
solutions.append((a, b, c))
return solutions
OP code
Modified OP code so it returns all solutions rather than printing the first found to compare performance
def pythagoreanTriplet(n):
# Considering triplets in
# sorted order. The value
# of first element in sorted
# triplet can be at-most n/3.
results = []
for i in range(1, int(n / 3) + 1):
# The value of second element
# must be less than equal to n/2
for j in range(i + 1,
int(n / 2) + 1):
k = n - i - j
if (i * i + j * j == k * k):
results.append((i, j, k))
return results
Timing
n pythagoreanTriplet (OP Code) solve_pythagorean_triplets (new)
900 0.084 seconds 0.039 seconds
5000 3.130 seconds 0.012 seconds
90000 Timed out after several minutes 0.430 seconds
Explanation
Function solve_pythagorean_triplets is O(n) algorithm that works as follows.
Searching for:
a^2 + b^2 = c^2 (triplet)
a + b + c = n (sum equals input)
Solve by searching over a (i.e. a fixed for an iteration). With a fixed, we have two equations and two unknowns (b, c):
b + c = n - a
c^2 - b^2 = a^2
Solution is:
denom = 2*(n-a)
num = 2*a**2 + n**2 - 2*n*a
if denom > 0 and num % denom == 0:
c = num // denom
b = n - a - c
if b > a:
(a, b, c) # is a solution
Iterate a range(1, n) to get different solutions
Edit June 2022 by #AbhijitSarkar:
For those who like to see the missing steps:
c^2 - b^2 = a^2
b + c = n - a
=> b = n - a - c
c^2 - (n - a - c)^2 = a^2
=> c^2 - (n - a - c) * (n - a - c) = a^2
=> c^2 - n(n - a - c) + a(n - a - c) + c(n - a - c) = a^2
=> c^2 - n^2 + an + nc + an - a^2 - ac + cn - ac - c^2 = a^2
=> -n^2 + 2an + 2nc - a^2 - 2ac = a^2
=> -n^2 + 2an + 2nc - 2a^2 - 2ac = 0
=> 2c(n - a) = n^2 - 2an + 2a^2
=> c = (n^2 - 2an + 2a^2) / 2(n - a)
DarrylG's answer is correct, and I've added the missing steps to it as well, but there's another solution that's faster than iterating from [1, n). Let me explain it, but I'll leave the code up to the reader.
We use Euclid's formula of generating a tuple.
a = m^2 - n^2, b = 2mn, c = m^2 + n^2, where m > n > 0 ---(i)
a + b + c = P ---(ii)
Combining equations (i) and (ii), we have:
2m^2 + 2mn = P ---(iii)
Since m > n > 0, 1 <= n <= m - 1.
Putting n=1 in equation (iii), we have:
2m^2 + 2m - P = 0, ax^2 + bx + c = 0, a=2, b=2, c=-P
m = (-b +- sqrt(b^2 - 4ac)) / 2a
=> (-2 +- sqrt(4 + 8P)) / 4
=> (-1 +- sqrt(1 + 2P)) / 2
Since m > 0, sqrt(b^2 - 4ac) > -b, the only solution is
(-1 + sqrt(1 + 2P)) / 2 ---(iv)
Putting n=m-1 in equation (iii), we have:
2m^2 + 2m(m - 1) - P = 0
=> 4m^2 - 2m - P = 0, ax^2 + bx + c = 0, a=4, b=-2, c=-P
m = (-b +- sqrt(b^2 - 4ac)) / 2a
=> (2 +- sqrt(4 + 16P)) / 8
=> (1 +- sqrt(1 + 4P)) / 4
Since m > 0, the only solution is
(1 + sqrt(1 + 4P)) / 4 ---(v)
From equation (iii), m^2 + mn = P/2; since P/2 is constant,
when n is the smallest, m must be the largest, and vice versa.
Thus:
(1 + sqrt(1 + 4P)) / 4 <= m <= (-1 + sqrt(1 + 2P)) / 2 ---(vi)
Solving equation (iii) for n, we have:
n = (P - 2m^2) / 2m ---(vii)
We iterate for m within the bounds given by the inequality (vi)
and check when the corresponding n given by equation (vii) is
an integer.
Despite generating all primitive triples, Euclid's formula does not
produce all triples - for example, (9, 12, 15) cannot be generated using
integer m and n. This can be remedied by inserting an additional
parameter k to the formula. The following will generate all Pythagorean
triples uniquely.
a = k(m^2 - n^2), b = 2kmn, c = k(m^2 + n^2), for k >= 1.
Thus, we iterate for integer values of P/k until P < 12,
lowest possible perimeter corresponding to the triple (3, 4, 5).
Yo
I don't know if you still need the answer or not but hopefully, this can help.
n = int(input())
ans = [(a, b, c) for a in range(1, n) for b in range(a, n) for c in range(b, n) if (a**2 + b**2 == c**2 and a + b + c == n)]
if ans:
print(ans[0][0], ans[0][1], ans[0][2])
else:
print("Impossible")

Iterative version of this recursive function

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

What's wrong with my DP solution for 0-1 Knapsack?

The question is classical 0-1 knapsack problem:
Given n items with size A[i], an integer m denotes the size of a backpack. How full you can fill this backpack?
Example
If we have 4 items with size [2, 3, 5, 7], the backpack size is 11, we can select 2, 3 and 5, so that the max size we can fill this backpack is 10. If the backpack size is 12. we can select [2, 3, 7] so that we can fulfill the backpack.
I wrote two solution for it, and the first recursion one works, but DP one doesn't.
class Solution:
# #param m: An integer m denotes the size of a backpack
# #param A: Given n items with size A[i]
# #return: The maximum size
def backPack(self, m, A):
if len(A) <= 0 or m <= 0:
return 0
if A[0] > m:
return self.backPack(m, A[1:])
put = A[0] + self.backPack(m - A[0], A[1:])
not_put = self.backPack(m, A[1:])
return max(put, not_put)
def YetAnotherBackPack(self, m, A):
mapping = [(m + 1) * [0]] * (len(A) + 1)
for i in range(len(A) + 1):
for j in range(m + 1):
if i == 0 or j == 0:
mapping[i][j] = 0
elif A[i - 1] > j:
mapping[i][j] = mapping[i - 1][j]
else:
put = mapping[i - 1][j - A[i - 1]] + A[i - 1]
mapping[i][j] = max(mapping[i - 1][j], put)
return mapping[len(A)][m]
print Solution().backPack(10, [3, 4, 8, 5]) # output: 9
print Solution().YetAnotherBackPack(10, [3, 4, 8, 5]) # output: 10 WRONG!
Can anyone help point that what's wrong with my DP solution?
This line is the problem:
mapping = [(m + 1) * [0]] * (len(A) + 1)
You're creating a list of lists, but you're not creating a unique inner list for each row - all of the rows are pointing to the same list (the one created by [(m + 1) * [0]].
To fix it, change that line to something like this:
mapping = [[0 for i in range(m+1)] for j in range(len(A) + 1)]
For a more detailed description of this issue: Nested List Indices

Unable to implement a dynamic programming table algorithm in python

I am having problems creating a table in python. Basically I want to build a table that for every number tells me if I can use it to break down another(its the table algo from the accepted answer in Can brute force algorithms scale?). Here's the pseudo code:
for i = 1 to k
for z = 0 to sum:
for c = 1 to z / x_i:
if T[z - c * x_i][i - 1] is true:
set T[z][i] to true
Here's the python implementation I have:
from collections import defaultdict
data = [1, 2, 4]
target_sum = 10
# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T = defaultdict(bool) # all values are False by default
T[0, 0] = True # base case
for i, x in enumerate(data): # i is index, x is data[i]
for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself
for c in range(s / x + 1):
if T[s - c * x, i]:
T[s, i+1] = True
#query area
target_result = 1
for node in T:
if node[0]==target_result:
print node, ':', T[node]
So what I expect is if target_result is set to 8, it shows how each item in list data can be used to break that number down. For 8, 1,2,4 for all work so I expect them all to be true, but this program is making everything true. For example, 1 should only be able to be broken down by 1(and not 2 or 4) but when I run it as 1, I get:
(1, 2) : True
(1, 0) : False
(1, 3) : True
(1, 1) : True
can anyone help me understand what's wrong with the code? or perhaps I am not understanding the algorithm that was posted in answer I am referring to.
(Note: I could be completely wrong, but I learned that defaultdict creates entries even if its not there, and if the entry exists the algo turns it to true, maybe thats the problem I'm not sure, but it was the line of thought I tried to go but it didn't work for me because it seems to break the overall implemention)
Thanks!
The code works if you print the solution using RecursivelyListAllThatWork():
coeff = [0]*len(data)
def RecursivelyListAllThatWork(k, sum): # Using last k variables, make sum
# /* Base case: If we've assigned all the variables correctly, list this
# * solution.
# */
if k == 0:
# print what we have so far
print(' + '.join("%2s*%s" % t for t in zip(coeff, data)))
return
x_k = data[k-1]
# /* Recursive step: Try all coefficients, but only if they work. */
for c in range(sum // x_k + 1):
if T[sum - c * x_k, k - 1]:
# mark the coefficient of x_k to be c
coeff[k-1] = c
RecursivelyListAllThatWork(k - 1, sum - c * x_k)
# unmark the coefficient of x_k
coeff[k-1] = 0
RecursivelyListAllThatWork(len(data), target_sum)
Output
10*1 + 0*2 + 0*4
8*1 + 1*2 + 0*4
6*1 + 2*2 + 0*4
4*1 + 3*2 + 0*4
2*1 + 4*2 + 0*4
0*1 + 5*2 + 0*4
6*1 + 0*2 + 1*4
4*1 + 1*2 + 1*4
2*1 + 2*2 + 1*4
0*1 + 3*2 + 1*4
2*1 + 0*2 + 2*4
0*1 + 1*2 + 2*4
As a side note, you don't really need a defaultdict with what you're doing, you can use a normal dict + .get():
data = [1, 2, 4]
target_sum = 10
T = {}
T[0, 0] = True
for i,x in enumerate(data):
for s in range(target_sum + 1): # xrange on python-2.x
for c in range(s // x + 1):
if T.get((s - c * x, i)):
T[s, i+1] = True
If you're using J.S. solution, don't forget to change:
if T[sum - c * x_k, k - 1]:
with:
if T.get((sum - c * x_k, k - 1)):
Your code is right.
1 = 1 * 1 + 0 * 2, so T[1, 2] is True.
1 = 1 * 1 + 0 * 2 + 0 * 4, so T[1, 3] is True.
As requested in the comments, a short explanation of the algo:
It calculates all numbers from 0 to targetsum that can be represented as a sum of (non-negative) multiples of some of the numbers in data.
If T[s, i] is True, then s can be represented in this way using only the first i elements of data.
At the start, 0 can be represented as the empty sum, thus T[0, 0] is True. (This step may seem a little technical.)
Let x be the 'i+1'-th element of data. Then, the algorithm tries for each number s if it can be represented by the sum of some multiple of x and a number for which a representation exists that uses only the first i elements of data (the existence of such a number means T[s - c * x, i] is True for some c). If so, s can be represented using only the first i+1 elements of data.

Categories

Resources