Fibbonaci-like sequence of last 3 numbers - python

Is there a non-recursive way I can make a "Fibonacci-like"sequence of the by adding the last 3 numbers?
Here's the recursive way I tried to do it.
def fib3(n):
if n < 3:
return 1
else:
return fib3(n-1) + fib3(n-2) + fib3(n-3)
returns 1+1+1+3+5+9+17...+(n-1) + (n-2) + (n-3)
Any help will be appreciated.
Thanks in advance

Yes, and quite elegantly, with Python's multiple assignment ability:
>>> def fib3(n):
... if n < 3:
... return 1
... a = b = c = 1
... for i in range(3, n):
... # We "shift" a, b, and c to the next values of the sequence.
... a, b, c = b, c, (a + b + c)
... return c
...
>>> fib3(4)
3
>>> fib3(5)
5
>>> fib3(6)
9
>>> fib3(7)
17
And the iterative method would definitely be preferred to the recursive method - as #mu writes, the running time of the recursive implementation is approximately O(3^n), while this method is O(n).

fib_sum to calculate m last integer:
>>> def fib_sum(n,m):
if n < m:
return "n should be greater than m"
a,b,sumit = 0,1,0
for x in range(n):
print b,
if x >= n-m:
sumit += b
a,b = b,a+b
return sumit
>>> fib_sum(3,4)
'n should be greater than m'
>>> fib_sum(3,2)
1 1 2
3
>>> fib_sum(3,1)
1 1 2
2
>>> fib_sum(2,1)
1 1
1
>>> fib_sum(2,2)
1 1
2
>>> fib_sum(7,2)
1 1 2 3 5 8 13
21
>>> fib_sum(7,3)
1 1 2 3 5 8 13
26
>>> fib_sum(8,6)
1 1 2 3 5 8 13 21
52
>>> fib_sum(8,8)
1 1 2 3 5 8 13 21
54

I've arrived late at the party, but: one can easily derive a formula to get the n'th element of any linear recurrence such as the Fibonacci sequence or a generalization of that, without having to compute all the intermediate elements. Say your recurrence is f[n] = a[1] f[n - 1] + a[2] f[n - 2] + ... + a[m] f[n - m]. Suppose that f[n] = (some constant)^n. (This is the kind of "lucky guess" hypothesis that often appears in solutions for differential equations. I don't know how to justify it a priori. It can be justified after the fact by actually finding such a constant.) Then the constant must be a root of the polynomial x^m - a[1] x^(m - 1) - a[2] x^(m - 2) - ... - a[m]. Any linear combination of solutions must also be a solution. You can find the coefficients c[1], ..., c[m] for the linear combination by solving the linear system derived from the first m values (obviously the value of all the later values in the sequence are determined by the first m values).
For the stated recurrence f[n] = f[n - 1] + f[n - 2] + f[n - 3], we have a[1] = a[2] = a[3] = 1 and the roots of x^3 - x^2 - x - 1 are - 0.6063 %i - 0.4196, 0.6063 %i - 0.4196, 1.839, respectively. It is given that the first 3 values are 1, 1, 1. Solving c[1] + c[2] + c[3] = 1, c[1] a[1] + c[2] a[2] + c[3] a[3] = 1, c[1] a[1]^2 + c[2] a[2]^2 + c[3] a[3]^2 = 1 for c[1], c[2], c[3] yields 0.3592 %i + 0.2822, 0.2822 - 0.3592 %i, 0.4356, respectively. (I've written these as approximate, floating point numbers. As roots of polynomials with rational coefficients, these are algebraic numbers, but exact expressions might easily become messy.)
In summary, f[n] = c[1] a[1]^n + c[2] a[2]^n + c[3] a[3]^n, with the stated values for the a's and c's, is a function which gives the n'th element of the recurrence f[n] = f[n - 1] + f[n - 2] + f[n - 3], with f[2] = f[1] = f[0] = 1.
I calculated the a's and c's in Maxima. I can say more about how I did that if there is any interest.

Related

Linearization of if-then constraint

I'm trying to linearize a constraint of this form:
if a == b then c = 1
where a and b are positive integers and c is a binary variable.
I'm looking for a solution like this one https://math.stackexchange.com/questions/2792360/how-to-linearize-if-then-constraint
which doesn't work in this case.
Thanks to anyone who can help me.
The implication
a = b => c = 1
(a,b: integer variables, c: a binary variable)
can be re-stated as:
c = 0 => a >= b + 1
or
a <= b - 1
(Using that a,b are integers). An "or" needs an extra binary variable. So we can write:
a >= b + 1 - M δ - M c
a <= b - 1 + M (1-δ) + M c
δ ∈ {0,1}
Here M is a large enough constant (to be chosen with care).

Given an N-side square matrix, is there a way to find the ring value of a cell without using loops or if conditions?

For instance, imagine you have a 6-side square matrix.
These are the cells cartesian indices:
(0,0) (0,1) (0,2) (0,3) (0,4) (0,5)
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5)
(2,0) (2,1) (2,2) (2,3) (2,4) (2,5)
(3,0) (3,1) (3,2) (3,3) (3,4) (3,5)
(4,0) (4,1) (4,2) (4,3) (4,4) (4,5)
(5,0) (5,1) (5,2) (5,3) (5,4) (5,5)
A 6-side square has 3 rings: a
A A A A A A
A B B B B A
A B C C B A
A B C C B A
A B B B B A
A A A A A A
QUESTION: What's the function that takes the coordinates of a cell, the side N of the square and returns the ring value accordingly? Ex:
f(x = 1, y 2, N = 6) = B
A,B,C... can be any numerical value: 1,2,3 ... or 0,1,2 ... or whatever. What matters is that they are congruent for any N. Ex:
N = 1 => A = 1
N = 2 => A = 1
N = 3 => A = 1, B = 2
N = 4 => A = 1, B = 2
N = 5 => A = 1, B = 2, C = 3
N = 6 => A = 1, B = 2, C = 3
N = 7 => A = 1, B = 2, C = 4, D = 4
...
Using if conditions the problem is easily solved.
Given a pair (x,y) and the square side N:
# N//2 is the number of rings in a N-side square
for k in range(1,N//2+1):
if x == 0+k-1 or y== 0+k-1 or x == N-k or y == N-1:
return k
This seems like a very expensive way to find the ring value of the cell though.
I have been trying to find the function using diagonals, sum of the coordinates, difference of the coordinates ... of the cells, but I still couldn't find anything.
Has anyone ever encountered this problem?
Is there a way to solve it?
Looks like a math problem to solve.
EDIT: Updated function, should be better able to handle even and odd cases after the mid point i hope. However, OP's request to turn this into a mathematical equation, i'm not sure how to do that.
import math
def ring_finder(x, y, N, outer_ring = 0):
'''
x and y are the coordinates of a cell, N is the length of the side of square
Returns the correct ring count starting from outer_ring value (default, 0)
'''
if x >= N or y >= N:
print("coordinates outside square, please check")
return None
no_of_squares = math.ceil(N/2)
x = N - x - 1 if x >= no_of_squares else x
y = N - y - 1 if y >= no_of_squares else y
return min(x, y) + outer_ring
ring_finder(5, 5, 6)
ring_finder(1, 2, 6)
I think this function does what you want:
def ring_id(n, i, j):
even = n % 2 == 0
n_2 = n // 2
i = i - n_2
if even and i >= 0:
i += 1
i = abs(i)
j = j - n_2
if even and j >= 0:
j += 1
j = abs(j)
ring_id = i + max(j - i, 0)
return n_2 - ring_id
Small test with letters:
import string
def print_rings(n):
ring_names = string.ascii_uppercase
for i in range(n):
for j in range(n):
rid = ring_id(n, i, j)
print(ring_names[rid], end=' ')
print()
print_rings(6)
# A A A A A A
# A B B B B A
# A B C C B A
# A B C C B A
# A B B B B A
# A A A A A A
print_rings(7)
# A A A A A A A
# A B B B B B A
# A B C C C B A
# A B C D C B A
# A B C C C B A
# A B B B B B A
# A A A A A A A
EDIT: If you insist in not having the word if in your function, you can (somewhat awkwardly) rewrite the above function as:
def ring_id(n, i, j):
even = 1 - n % 2
n_2 = n // 2
i = i - n_2
i += even * (i >= 0)
i = abs(i)
j = j - n_2
j += even * (j >= 0)
j = abs(j)
ring_id = i + max(j - i, 0)
return n_2 - ring_id
Or if you want it looking more "formula-like" (albeit unreadable and with more repeated computation):
def ring_id(n, i, j):
i2 = abs(i - (n // 2) + (1 - n % 2) * (i >= (n // 2)))
j2 = abs(j - (n // 2) + (1 - n % 2) * (j >= (n // 2)))
return (n // 2) - i2 + max(j2 - i2, 0)
This is not any more or less "mathematical" though, it is fundamentally the same logic.
The ring value is the complement of the distance to the center of the array, in the "infinity norm" sense.
N/2 - max(|X - (N-1)/2|, |Y - (N-1)/2|).
This assigns the value 0 for A, 1 for B and so on.
To avoid the half integers, you can use
(N - min(|2X - N + 1|, |2Y - N + 1|) / 2.
The max and abs functions may involve hidden ifs, but you can't avoid that.
def Ring(X, Y, N):
return (N - max(abs(2 * X - N + 1), abs(2 * Y - N + 1))) // 2
for N in range(1, 8):
for X in range(N):
for Y in range(N):
print(chr(Ring(X, Y, N) + 65), '', end= '')
print()
print()
A
A A
A A
A A A
A B A
A A A
A A A A
A B B A
A B B A
A A A A
A A A A A
A B B B A
A B C B A
A B B B A
A A A A A
A A A A A A
A B B B B A
A B C C B A
A B C C B A
A B B B B A
A A A A A A
A A A A A A A
A B B B B B A
A B C C C B A
A B C D C B A
A B C C C B A
A B B B B B A
A A A A A A A

python: algorithm for swapping elements between two arrays

I am analyzing counting example in python presented by Codility
I don't understand the logic used in the last loop (5 last rows) of this algorithm.
Can anybody help please?
The problem:
You are given an integer m (1 < m < 1000000) and two non-empty,
zero-indexed arrays A and B of n integers, a0, a1, ... ,
an−1 and b0, b1, ... , bn−1 respectively (0 < ai, bi < m).
The goal is to check whether there is a swap operation which can be
performed on these arrays in such a way that the sum of elements in
array A equals the sum of elements in array B after the swap. By
swap operation we mean picking one element from array A and one
element from array B and exchanging them.
The solution:
def counting(A, m):
n = len(A)
count = [0] * (m + 1)
for k in xrange(n):
count[A[k]] += 1
return count
def fast_solution(A, B, m):
n = len(A)
sum_a = sum(A)
sum_b = sum(B)
d = sum_b - sum_a
if d % 2 == 1:
return False
d //= 2
count = counting(A, m)
for i in xrange(n):
if 0 <= B[i] - d and B[i] - d <= m and count[B[i] - d] > 0:
return True
return False
What I would recommend you is read again the explanations given in the exercise. It already explains what how the algorithm works. However, if you still have problems with it, then take a piece of paper, and some very simple example arrays and go through the solution step by step.
For example, let A = [6, 6, 1, 2, 3] and B = [1, 5, 3, 2, 1].
Now let's go through the algorithm.
I assume you understand how this method works:
def counting(A, m):
n = len(A)
count = [0] * (m + 1)
for k in xrange(n):
count[A[k]] += 1
return count
It just returns a list with counts as explained in the exercise. For list A and m = 10 it will return:
[0, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0]
Then we go through the main method fast_solution(A, B, m):
n = 11 (this will be used in the loop)
The sum of A equals 18 and the sum of B equals 12.
The difference d is -6 (sum_b - sum_a), it is even. Note that if difference is odd, then no swap is available and the result is False.
Then d is divided by 2. It becomes -3.
For A we get count [0, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0] (as already mentioned before).
Then we just iterate though the list B using xrange and check the conditions (The loop goes from 0 and up to but not including 11). Let's check it step by step:
i = 0, B[0] - (-3) is 1 + 3 = 4. 4 is greater than or equal to 0 and less than or equal to 10 (remember, we have chosen m to be 10). However, count[4] is 0 and it's not greater than 0 (Note the list count starts from index 0). The condition fails, we go further.
i = 1, B[1] - (-3) is 5 + 3 = 8. 8 is greater than or equal to 0 and less than or equal to 10. However, count[8] is 0 and the condition fails.
i = 2, B[2] - (-3) is 3 + 3 = 6. 6 is greater than 0 and less than 10. Also count[6] is 2 and it is greater than 0. So we found the number. The loop stops, True is returned. It means that there is such a number in B which can be swapped with a number in A, so that sum of A becomes equal to the sum of B. Indeed, if we swap 6 in A with 3 in B, then their sum become equal to 15.
Hope this helps.
I'm not sure I get your idea correctly. Here's my understanding:
def counting(A, m):
n = len(A)
count = [0] * (m + 1)
for k in xrange(n):
count[A[k]] += 1
return count # this essentially build a counter
def fast_solution(A, B, m):
n = len(A)
sum_a = sum(A)
sum_b = sum(B)
d = sum_b - sum_a
if d % 2 == 1:
return False
d //= 2
count = counting(A, m) # get the dict
for i in xrange(n):
if 0 <= B[i] - d and B[i] - d <= m and count[B[i] - d] > 0:
# the first two conditions are to verify that B[i]-d exists as a key (index) in counter.
# then check if there actually exists the value.
# if count > 0, then you can swap the two to get same sum
return True
return False
Or rewriting to get:
def counting(A, m):
count = collections.Counter()
for i in A:
count[i] += 1
return count
def fast_solution(A, B, m):
n = len(A)
sum_a = sum(A)
sum_b = sum(B)
d = sum_b - sum_a
if d % 2 == 1:
return False
d //= 2
count = counting(A, m) # get the dict
for i in B:
if count[i-d]:
return True
return False
But in any case, this piece of code just check the solution existence with only single swap, be sure to check if that's what you wanted.

Sum of 2 elements from 2 ranges that will be one given number

I need to make a quick algorithm(I already made a slow one) which will find the number of all possible values from two ranges of integer numbers (ranges can intersect or not) which sum will be the given number
I can represent it like an equation: z = x + y
where z is a known number and equals x plus y
z can be any number between 0 and 10^18
x belongs to a range of integer numbers [a..b], where 0 <= a <= b <= 10^18 and
the difference between the consecutive numbers is 1
y belongs to a range of integer numbers [c..d], where 0 <= c <= d <= 10^18 and
the difference between the consecutive numbers is 1
so I need to find the number(not their exact values) of all the possible variations of x and y from two sets of numbers which sum will be z
Example:
z = 5
first set: a = 1, b = 5(it means the set consists of 1,2,3,4,5)
second set: c = 1, b = 5
then the answer is 4, because all possible combinations are:
x = 4, y = 1
x = 3, y = 2
x = 2, y = 3
x = 1, y = 4
because theirs sums are 5's
The compulsory condition for an algrorithm is to work faster than 1 second
The following code works fine but only with numbers lesser than 1000000. It starts to work much slower with big numbers
with open(r"input.txt") as f:
n = int(f.readline()) # the given number
a = int(f.readline()) # the start position of the first set
b = int(f.readline()) # the end position of the first set
c = int(f.readline()) # the start position of the second set
d = int(f.readline()) # the end position of the second set
# print "n:",n,"a:",a,"b:",b,"c:",c,"d:",d
t = b - a + 1 # all posible variants of the first set
k = d - c + 1 # all posible variants of the second set
number_of_vars = 0
if t >= k:
while b >= a:
if (n - b <= d) \
and (n - b>= c):
number_of_vars += 1
b -= 1
else:
b -= 1
if t < k:
while d >= c:
if (n-d <= b) and (n-d >= a):
number_of_vars += 1
d -= 1
else:
d -= 1
print number_of_vars
No algorithm required -- just algebra:
It suffices to count the number of x in [a,b] for which z - x is in [c,d]
You need both a <= x <= b and c <= z - x <= d. The second inequality is equivalent to z - d <= x <= z - c hence you need
max(a, z - d) <= x <= min(b,z - c)
The number of such x is 0 if min(b,z - c) < max(a, z - d) otherwise it is
min(b,z - c) - max(a, z - d) + 1
In either case the number of solutions is
max(0, min(b,z - c) - max(a, z - d) + 1)
In your example a = c = 1 and b = d = z = 5 and
min(b, z - c) - max(a, z - d) + 1 = min(5,4) - max(1,0) + 1 = 4 - 1 + 1 = 4
One thing that you can use to reduce the checks in your algorithm is,
If the range for the 2 sets are overlapping, then you can cancel out some checks. Like in your example,
range for 1st set is 1 to 5
range for 2nd set is 1 to 5
So, if
x = 4, y = 1
is working, then
x = 1, y = 4
will also work. So you have to go only till half the number (i.e till 3 only in this case)
If only a part of the range is overlapping, then you can use the above method for that part, and the remaining part can be checked using normal method.

Calculate the extended gcd using a recursive function in Python

I am given the function gcd, which is defined as follows:
def gcd(a, b):
if (0 == a % b):
return b
return gcd(b, a%b)
Now I am asked to write a recursive function gcd2(a,b) that returns a list of three numbers (g, s, t) where g = gcd(a, b) and g = s*a + t*b.
This means that you would enter two values (a and b) into the gcd(a, b) function. The value it returns equals g in the next function.
These same a and b values are then called into gcd2(a, b). The recursive part is then used to find the values for s and t so that g = s*a + t*b.
I am not sure how to approach this because I can't really envision what the "stopping-condition" would be, or what exactly I'd be looping through recursively to actually find s and t. Can anyone help me out?
The key insight is that we can work backwards, finding s and t for each a and b in the recursion. So say we have a = 21 and b = 15. We need to work through each iteration, using several values -- a, b, b % a, and c where a = c * b + a % b. First, let's consider each step of the basic GCD algorithm:
21 = 1 * 15 + 6
15 = 2 * 6 + 3
6 = 2 * 3 + 0 -> end recursion
So our gcd (g) is 3. Once we have that, we determine s and t for 6 and 3. To do so, we begin with g, expressing it in terms of (a, b, s, t = 3, 0, 1, -1):
3 = 1 * 3 + -1 * 0
Now we want to eliminate the 0 term. From the last line of the basic algorithm, we know that 0 = 6 - 2 * 3:
3 = 1 * 3 + -1 * (6 - 2 * 3)
Simplifying, we get
3 = 1 * 3 + -1 * 6 + 2 * 3
3 = 3 * 3 + -1 * 6
Now we swap the terms:
3 = -1 * 6 + 3 * 3
So we have s == -1 and t == 3 for a = 6 and b = 3. So given those values of a and b, gcd2 should return (3, -1, 3).
Now we step back up through the recursion, and we want to eliminate the 3 term. From the next-to-last line of the basic algorithm, we know that 3 = 15 - 2 * 6. Simplifying and swapping again (slowly, so that you can see the steps clearly...):
3 = -1 * 6 + 3 * (15 - 2 * 6)
3 = -1 * 6 + 3 * 15 - 6 * 6
3 = -7 * 6 + 3 * 15
3 = 3 * 15 + -7 * 6
So for this level of recursion, we return (3, 3, -7). Now we want to eliminate the 6 term.
3 = 3 * 15 + -7 * (21 - 1 * 15)
3 = 3 * 15 + 7 * 15 - 7 * 21
3 = 10 * 15 - 7 * 21
3 = -7 * 21 + 10 * 15
And voila, we have calculated s and t for 21 and 15.
So schematically, the recursive function will look like this:
def gcd2(a, b):
if (0 == a % b):
# calculate s and t
return b, s, t
else:
g, s, t = gcd2(b, a % b)
# calculate new_s and new_t
return g, new_s, new_t
Note that for our purposes here, using a slightly different base case simplifies things:
def gcd2(a, b):
if (0 == b):
return a, 1, -1
else:
g, s, t = gcd2(b, a % b)
# calculate new_s and new_t
return g, new_s, new_t
The base case (stopping condition) is:
if a%b == 0:
# a = b*k for the integer k=a/b
# rearranges to b = -1*a + (k+1)*b
# ( g = s*a + t*b )
return (b, -1, a/b+1) # (g, s, t)
However the exercise is to rewrite the recursive part:
g1, s1, t1 = gcd(b, a%b) # where g1 = s1*b + t1*(a%b)
g, s, t = ??? # where g = s*a + t*b
return (g, s, t)
in terms of g1, s1 and t1... which boils down to rewriting a%b in terms of a and b.
"Write a recursive function in Python", at least in CPython, cries for this: be aware of http://docs.python.org/library/sys.html#sys.getrecursionlimit. This is, in my opinion, one of the most important answers to this question. Please do some research on this topic yourself. Also, this thread might be insightful: Python: What is the hard recursion limit for Linux, Mac and Windows?
In conclusion, try to use an iterative instead of a recursive approach in Python whenever possible.
It is based on Euclidian algorithm using better to while loop continued recursion even better and less execution
def gcd(m,n):
#assume m>= n
if m <n:
(m,n) = (n,m)
if (m%n) == 0:
return(n)
else:
diff =m-n
#diff >n ?Possible!
return(gcd(max(n,diff),min(n,diff)))
it can be better by while loop
def gcd(m,n):
if m<n :
(m,n) =(n,m)
while (m%n) !=0:
diff =m-n
(m,n) =(max(n,diff),min(n,diff))
return(n)

Categories