Product of 2 fibonacci numbers - python

My assignment:
Given a number, say prod (for product), we search two Fibonacci
numbers F(n) and F(n+1) verifying
F(n) * F(n+1) = prod if F(n) * F(n+1) = prod
Your function productFib takes an integer (prod) and returns an array:
[F(n), F(n+1), True] else
F(m) being the smallest one such as F(m) * F(m+1) > prod
[F(m), F(m+1), False]
Examples:
productFib(714) # should return [21, 34, True],
# since F(8) = 21, F(9) = 34 and 714 = 21 * 34
productFib(800) # should return [34, 55, False],
# since F(8) = 21, F(9) = 34, F(10) = 55 and 21 * 34 < 800 < 34 * 55
My code:
def f(i):
if i == 0 :
return 0
if i == 1 :
return 1
return f(i-2) + f(i-1)
def productFib(prod):
i=1
final1 = 0
final2 = 0
while(f(i)*f(i+1) != prod and f(i)*f(i+1) < prod):
i += 1
final1 = f(i)
final2 = f(i+1)
if(final1*final2 == prod):
return [final1,final2,True]
else:
return [final1,final2,False]
I am new to programming; this runs very slow for large numbers. How can I reduce the time complexity?

def productFib(prod):
a, b = 0, 1
while prod > a * b:
a, b = b, a + b
return [a, b, prod == a * b]

First and foremost, your f function is horridly time-consuming: it computes f(n) for low n many times. Memoize the function: keep results in a list, and just refer to that list when you compute again.
memo = [1, 1]
def f(i):
global memo
if i >= len(memo):
# Compute all f(k) where k < i
f_of_i = f(i-2) + f(i-1)
memo.append(f_of_i)
return memo[i]
Note that this sequence still guarantees that you will fill in memo in numerical order: f(i-2) is called before f(i-1), and both are called before adding f(i) to the list.
Calling f(100000000000000) (10^14) with this returns instantaneously. I haven't tried it with higher numbers.
UPDATE
I ran it with increasing powers of 10. At 10^1650, it was still printing output at full speed, and I interrupted the run.
IMPROVEMENT
You can do even better (for many applications) by directly computing f(i) from the closed-form equation:
root5 = 5 ** 0.5
phi = (1 + root5) / 2
psi = (1 - root5) / 2
def f(i):
return int(round((phi ** i - psi ** i) / root5))
MORE IMPROVEMENT
Directly compute the proper value of i.
f(i) * f(i+1) is very close to phi**(2i+1) / 5.
def productFib(prod):
power = math.log(prod*5) / log_phi
i = int(round(power-1, 7)/2) + 1
low = f(i)
high = f(i+1)
# print i, low, high
answer = [low, high, low*high == prod]
return answer
print productFib(714)
print productFib(800)
print productFib(100000000000000000)
Output:
[21, 34, True]
[34, 55, False]
[267914296, 433494437, False]

You can increase the performance quite a bit by making use of a generator.
def fib():
# Generator that yields the last two fibonacci numbers on each iteration.
# Initialize
np = 0
n = 1
# Loop forever. The main function will break the loop.
while True:
# Calculate the next number
nn = np + n
# Yield the previous number and the new one.
yield n, nn
# Update the generator state.
np = n
n = nn
def product_fib(prod):
# Loop through the generator.
for f_0, f_1 in fib():
# If the product is larger or equal to the product return.
if f_0 * f_1 >= prod:
# The last element in the list is the resut of the equality check.
return [f_0, f_1, f_0 * f_1 == prod]
t0 = perf_counter()
res = productFib(8000000000)
t = perf_counter() - t0
print("Original:", t, res)
t0 = perf_counter()
res = product_fib(8000000000) # 8000000000
t = perf_counter() - t0
print("New:", t, res)
The output of this is
Original: 0.8113621789962053 [75025, 121393, False]
New: 1.3276992831379175e-05 [75025, 121393, False]
Edit
If you want a single line. It works, but don't use it, it's not really the most practical solution. The first one is faster anyways.
print((lambda prod: (lambda n: next(([a, b, (a * b) == prod] for a, b in ([n.append(n[0] + n[1]), n.pop(0), n][-1] for _ in iter(int, 1)) if (a * b) >= prod)))([0, 1]))(714))

Your fib function is recalculating from the bottom every time. You should save values you already know. My python is rusty, but I think this will do it:
dict = {}
def f(i):
if dict.has_key(i):
return dict[i]
if i == 0 :
return 0
if i == 1 :
return 1
sum = f(i-2) + f(i-1)
dict[i] = sum
return sum
def productFib(prod):
i=1
final1 = 0
final2 = 0
while(f(i)*f(i+1) != prod and f(i)*f(i+1) < prod):
i += 1
final1 = f(i)
final2 = f(i+1)
if(final1*final2 == prod):
return [final1,final2,True]
else:
return [final1,final2,False]

Here are a couple of different algorithms that are increasingly optimized (starting with the original algorithm).
Algorithm 3 uses an iterative fibonacci with caching along with guessing the square root (which should be between the two multiples of the fibonacci product).
Timing Results:
Original algorithm: 4.43634369118898
Algorithm 2 (recursive fib): 1.5160450420565503
Algorithm 2 (iter fib): 0.03543769357344395
Algorithm 2 (iter fib + caching): 0.013537414072276377
Algorithm 3 (iter fib + caching + guessing): 0.0017255337946799898
Setup:
import timeit
from random import randint
from math import sqrt
from bisect import bisect
cache = [0, 1]
Nth Fibonacci Number Algorithms:
def f(n):
"""Recursive solution: O(2^n)"""
if n == 0:
return 0
if n == 1:
return 1
return f(n-2) + f(n-1)
def ff(n):
"""Iterative solution: O(n)"""
a, b = 0, 1
for _ in range(0, n):
a, b = b, a + b
return a
def fff(n):
"""Iterative solution + caching"""
length = len(cache)
if n >= length:
for i in range(length, n+1):
cache.append(cache[i-1] + cache[i-2])
return cache[n]
Fibonacci Product Algorithms:
def pf1(prod):
"""Original algorithm."""
i=1
final1 = 0
final2 = 0
while(f(i)*f(i+1) != prod and f(i)*f(i+1) < prod):
i += 1
final1 = f(i)
final2 = f(i+1)
if(final1*final2 == prod):
return [final1,final2,True]
else:
return [final1,final2,False]
def pf2(prod, fib_func):
"""Algorithm 2.
Removes extra logic and duplicate function calls."""
i = 1
guess = 0
while guess < prod:
final1 = fib_func(i)
final2 = fib_func(i + 1)
guess = final1 * final2
i += 1
return [final1, final2, guess == prod]
def pf3(prod, fib_func):
"""Algorithm 3.
Implements square root as a guess."""
guess = sqrt(prod) # Numbers will be near square root
i = 2
while cache[-1] < guess:
fff(i)
i += 1
insertion_spot = bisect(cache, guess)
test1 = cache[insertion_spot-1]
test2 = cache[insertion_spot]
return [test1, test2, (test1 * test2) == prod]
Testing & Output:
prods = [randint(3, 99999) for _ in range(1000)] # 1000 random products
print("Original algorithm: ", timeit.timeit("for prod in prods: pf1(prod)", number=1, setup="from __main__ import pf1, prods"))
print("Algorithm 2 (recursive fib): ", timeit.timeit("for prod in prods: pf2(prod, f)", number=1, setup="from __main__ import pf2, prods, f"))
print("Algorithm 2 (iter fib): ", timeit.timeit("for prod in prods: pf2(prod, ff)", number=1, setup="from __main__ import pf2, prods, ff"))
print("Algorithm 2 (iter fib + caching): ", timeit.timeit("for prod in prods: pf2(prod, fff)", number=1, setup="from __main__ import pf2, prods, fff"))
print("Algorithm 3 (iter fib + caching + guessing):", timeit.timeit("for prod in prods: pf3(prod, fff)", number=1, setup="from __main__ import pf3, prods, fff, cache; cache = [0, 1]"))
Helpful Time Complexities of Python "List" object: https://wiki.python.org/moin/TimeComplexity

You may use the following code for your ProductFib function
def productFib2(prod):
i=0
final1 = f(i)
final2 = f(i+1)
while(final1 * final2 < prod):
i += 1
final1 = final2
final2 = f(i+1)
if(final1*final2 == prod):
return [final1,final2,True]
else:
return [final1,final2,False]

Two ways: slow and fast way to do it
Slow:
def productFib(prod):
i=0
final1 = f(i)
final2 = f(i+1)
while(final1 * final2 < prod):
i += 1
final1 = final2 #this is the same as final1 = f(i) again but, the value is already in memory no need to recalc it
final2 = f(i+1)
if(final1*final2 == prod):
return [final1,final2,True]
else:
return [final1,final2,False] #if non equivilant product
def f(i): #fib(0) == 0 fib(1) == 1
if i == 0 :
return 0
if i == 1 :
return 1
return f(i-2) + f(i-1)
output of the product in the while loop:
0
1
2
6
15
Fast:
def productFib(prod):
a, b = 0, 1
while prod > a * b:
1. List item
a, b = b, a + b #a is equal to b and b is equal to the sum of a and b
return [a, b, prod == a * b] #return a and b as well as the conditional if a times b is equal to the product
You don't need to check if something is apart of the fib series here because we can simply iterate over the series within the while loop without having to call another function recursively
the fib function is defined as: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. therefore, you can generate this with the algorithm in the while loop above
following that a = 0, b = 1 next a = 1, b = 1 next a = 1, b = 2 next a = 2, b = 3
next a = 3, b = 5 ...

Related

Sum of 1+3+5...+n until the sum exceeds 100

Then the sum and the last added number and the number of numbers added must be printed.
I am currently stuck, I managed to get the sum part working. The last added number output is printed "23" but should be "21". And lastly, how can I print the number of numbers added?
Output goal: 121, 21, 11
Here is my code:
n = int()
sum = 0
k = 1
while sum <= 100:
if k%2==1:
sum = sum + k
k = k + 2
print('Sum is:', sum)
print("last number:", k)
Edit: Would like to thank everyone for their help and answers!
Note, that (you can prove it by induction)
1 + 3 + 5 + ... + 2 * n - 1 == n**2
<----- n items ----->
So far so good in order to get n all you have to do is to compute square root:
n = sqrt(sum)
in case of 100 we can find n when sum reach 100 as
n = sqrt(100) == 10
So when n == 10 then sum == 100, when n = 11 (last item is 2 * n - 1 == 2 * 11 - 1 == 21) the sum exceeds 100: it will be
n*n == 11 ** 2 == 121
In general case
n = floor(sqrt(sum)) + 1
Code:
def solve(s):
n = round(s ** 0.5 - 0.5) + 1;
print ('Number of numbers added: ', n);
print ('Last number: ', 2 * n - 1)
print ('Sum of numbers: ', n * n)
solve(100)
We have no need in loops here and can have O(1) time and space complexity solution (please, fiddle)
More demos:
test : count : last : sum
-------------------------
99 : 10 : 19 : 100
100 : 11 : 21 : 121
101 : 11 : 21 : 121
Change your while loop so that you test and break before the top:
k=1
acc=0
while True:
if acc+k>100:
break
else:
acc+=k
k+=2
>>> k
21
>>> acc
100
And if you want the accumulator to be 121 just add k before you break:
k=1
acc=0
while True:
if acc+k>100:
acc+=k
break
else:
acc+=k
k+=2
If you have the curiosity to try a few partial sums, you immediately recognize the sequence of perfect squares. Hence, there are 11 terms and the last number is 21.
print(121, 21, 11)
More seriously:
i, s= 1, 1
while s <= 100:
i+= 2
s+= i
print(s, i, (i + 1) // 2)
Instead of
k = k + 2
say
if (sum <= 100):
k = k +2
...because that is, after all, the circumstance under which you want to add 2.
To also count the numbers, have another counter, perhasp howManyNumbers, which starts and 0 and you add 1 every time you add a number.
Just Simply Change you code to,
n = int()
sum = 0
k = 1
cnt = 0
while sum <= 100:
if k%2==1:
sum = sum + k
k = k + 2
cnt+=1
print('Sum is:', sum)
print("last number:", k-2)
print('Number of Numbers Added:', cnt)
Here, is the reason,
the counter should be starting from 0 and the answer of the last printed number should be k-2 because when the sum exceeds 100 it'll also increment the value of k by 2 and after that the loop will be falls in false condition.
You can even solve it for the general case:
def sum_n(n, k=3, s =1):
if s + k > n:
print('Sum is', s + k)
print('Last number', k)
return
sum_n(n, k + 2, s + k)
sum_n(int(input()))
You can do the following:
from itertools import count
total = 0
for i, num in enumerate(count(1, step=2)):
total += num
if total > 100:
break
print('Sum is:', total)
print("last number:", 2*i + 1)
To avoid the update on k, you can also use the follwoing idiom
while True:
total += k # do not shadow built-in sum
if total > 100:
break
Or in Python >= 3.8:
while (total := total + k) <= 100:
k += 2
Based on your code, this would achieve your goal:
n = 0
summed = 0
k = 1
while summed <= 100:
n += 1
summed = summed + k
if summed <= 100:
k = k + 2
print(f"Sum is: {summed}")
print(f"Last number: {k}")
print(f"Loop count: {n}")
This will solve your problem without changing your code too much:
n = int()
counter_sum = 0
counter = 0
k = 1
while counter_sum <= 100:
k+= 2
counter_sum =counter_sum+ k
counter+=1
print('Sum is:', counter_sum)
print("last number:", k)
print("number of numbers added:", counter)
You don't need a loop for this. The sum of 1...n with step size k is given by
s = ((n - 1) / k + 1) * (n + 1) / k
You can simplify this into a standard quadratic
s = (n**2 - k * n + k - 1) / k**2
To find integer solution for s >= x, solve s = x and take the ceiling of the result. Apply the quadratic formula to
n**2 - k * n + k - 1 = k**2 * x
The result is
n = 0.5 * (k + sqrt(k**2 - 4 * (k - k**2 * x - 1)))
For k = 2, x = 100 you get:
>>> from math import ceil, sqrt
>>> k = 2
>>> x = 100
>>> n = 0.5 * (k + sqrt(k**2 - 4 * (k - k**2 * x - 1)))
>>> ceil(n)
21
The only complication arises when you get n == ceil(n), since you actually want s > x. In that case, you can test:
c = ceil(n)
if n == c:
c += 1

Performing prime value pairs in python

I am currently stuck on Project Euler problem 60. The problem goes like this:
The primes 3, 7, 109, and 673, are quite remarkable. By taking any two primes and concatenating them in any order the result will always be prime. For example, taking 7 and 109, both 7109 and 1097 are prime. The sum of these four primes, 792, represents the lowest sum for a set of four primes with this property.
Find the lowest sum for a set of five primes for which any two primes concatenate to produce another prime.
In Python, I used and created the following functions.
def isprime(n):
"""Primality test using 6k+-1 optimization."""
if n <= 3:
return n > 1
elif n % 2 == 0 or n % 3 == 0:
return False
i = 5
while i * i <= n:
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return True
def prime_pair_sets(n):
heap = [[3,7]]
x = 11
#Phase 1: Create a list of length n.
while getMaxLength(heap)<n:
if isprime(x):
m = [x]
for lst in heap:
tmplst = [x]
for p in lst:
if primePair(x,p):
tmplst.append(p)
if len(tmplst)>len(m):
m=tmplst
heap.append(m)
x+=2
s = sum(maxList(heap))
#Phase 2: Find the lowest sum.
for li in heap:
y=x
while s>(sum(li)+y) and len(li)<n:
b = True
for k in li:
if not primePair(k,y):
b = False
if b == True:
li.append(y)
y+=2
if len(li)>=n:
s = sum(li)
return s
def getMaxLength(h):
m = 0
for s in h:
if len(s) > m:
m = len(s)
return m
def primePair(x, y):
return isprime(int(str(x)+str(y))) and isprime(int(str(y)+str(x)))
def maxList(h):
result = []
for s in h:
if len(s)> len(result):
result = s
return result
I executed the primePairSets function using the first phase only. After about an hour of waiting I got the sum of 74,617 (33647 + 23003 + 16451 + 1493 + 23). It turns out that it is not the sum we're looking for. I tried the problem again using both phases. After about two hours, I end up with the same wrong result. Obviously, the answer is less than 74,617. Can somebody help me find a more efficient way to solving this problem. Please tell me how to solve it.
Solution found
Primes: 13, 5197, 5701, 6733, 8389
Sum: 26,033
Run time reduced to ~10 seconds vs. 1-2 hours reported by OP solution.
Approach
Backtracking algorithm based upon extending path containing list of primes
A prime can be added to the path if its pairwise prime with all primes already in path
Use Sieve of Eratosthenes to precompute primes up to max we expect to need
For each prime, precompute which other primes it is pairwise prime with
Code
import functools
import time
# Decorator for function timing
def timer(func):
"""Print the runtime of the decorated function"""
#functools.wraps(func)
def wrapper_timer(*args, **kwargs):
start_time = time.perf_counter() # 1
value = func(*args, **kwargs)
end_time = time.perf_counter() # 2
run_time = end_time - start_time # 3
print(f"Finished {func.__name__!r} in {run_time:.4f} secs")
return value
return wrapper_timer
#*************************************************************
# Prime number algorithms
#-------------------------------------------------------------
def _try_composite(a, d, n, s):
if pow(a, d, n) == 1:
return False
for i in range(s):
if pow(a, 2**i * d, n) == n-1:
return False
return True # n is definitely composite
def is_prime(n, _precision_for_huge_n=16, _known_primes = set([2, 3, 5, 7])):
if n in _known_primes:
return True
if n > 6 and not (n % 6) in (1, 5):
# Check of form 6*q +/- 1
return False
if any((n % p) == 0 for p in _known_primes) or n in (0, 1):
return False
d, s = n - 1, 0
while not d % 2:
d, s = d >> 1, s + 1
# Returns exact according to http://primes.utm.edu/prove/prove2_3.html
if n < 1373653:
return not any(_try_composite(a, d, n, s) for a in (2, 3))
if n < 25326001:
return not any(_try_composite(a, d, n, s) for a in (2, 3, 5))
if n < 118670087467:
if n == 3215031751:
return False
return not any(_try_composite(a, d, n, s) for a in (2, 3, 5, 7))
if n < 2152302898747:
return not any(_try_composite(a, d, n, s) for a in (2, 3, 5, 7, 11))
if n < 3474749660383:
return not any(_try_composite(a, d, n, s) for a in (2, 3, 5, 7, 11, 13))
if n < 341550071728321:
return not any(_try_composite(a, d, n, s) for a in (2, 3, 5, 7, 11, 13, 17))
# otherwise
return not any(_try_composite(a, d, n, s)
for a in _known_primes[:_precision_for_huge_n])
def primes235(limit):
' Prime generator using Sieve of Eratosthenes with factorization wheel of 2, 3, 5 '
# Source: https://rosettacode.org/wiki/Sieve_of_Eratosthenes#Python
yield 2; yield 3; yield 5
if limit < 7: return
modPrms = [7,11,13,17,19,23,29,31]
gaps = [4,2,4,2,4,6,2,6,4,2,4,2,4,6,2,6] # 2 loops for overflow
ndxs = [0,0,0,0,1,1,2,2,2,2,3,3,4,4,4,4,5,5,5,5,5,5,6,6,7,7,7,7,7,7]
lmtbf = (limit + 23) // 30 * 8 - 1 # integral number of wheels rounded up
lmtsqrt = (int(limit ** 0.5) - 7)
lmtsqrt = lmtsqrt // 30 * 8 + ndxs[lmtsqrt % 30] # round down on the wheel
buf = [True] * (lmtbf + 1)
for i in range(lmtsqrt + 1):
if buf[i]:
ci = i & 7; p = 30 * (i >> 3) + modPrms[ci]
s = p * p - 7; p8 = p << 3
for j in range(8):
c = s // 30 * 8 + ndxs[s % 30]
buf[c::p8] = [False] * ((lmtbf - c) // p8 + 1)
s += p * gaps[ci]; ci += 1
for i in range(lmtbf - 6 + (ndxs[(limit - 7) % 30])): # adjust for extras
if buf[i]: yield (30 * (i >> 3) + modPrms[i & 7])
def prime_pair(x, y):
' Checks if two primes are prime pair (i.e. concatenation of two in either order is also a prime)'
return is_prime(int(str(x)+str(y))) and is_prime(int(str(y)+str(x)))
def find_pairs(primes):
' Creates dictionary of what primes can go with others as a pair'
prime_pairs = {}
for i, p in enumerate(primes):
pairs = set()
for j in range(i+1, len(primes)):
if prime_pair(p, primes[j]):
pairs.add(primes[j])
prime_pairs[p] = pairs
return prime_pairs
#*************************************************************
# Main functionality
#-------------------------------------------------------------
#timer
def find_groups(max_prime = 9000, n = 5):
'''
Find group smallest sum of primes that are pairwise prime
max_prime - max prime to consider
n - the size of the group
'''
def fully_connected(p, path):
'''
checks if p is connected to all elements of the path
(i.e. group of primes)
'''
return all(p in prime_pairs.get(path_item, set()) for path_item in path)
def backtracking(prime_pairs, n, path = None):
if path is None:
path = []
if len(path) == n:
yield path[:]
else:
if not path:
for p, v in prime_pairs.items():
if v:
yield from backtracking(prime_pairs, n, path + [p])
else:
p = path[-1]
for t in sorted(prime_pairs[p]):
if t > p and fully_connected(t, path):
yield from backtracking(prime_pairs, n, path + [t])
primes = list(primes235(max_prime)) # Sieve for list of primes up to max_pair
set_primes = set(primes) # set of primes (for easy test if number is prime)
prime_pairs = find_pairs(primes) # Table of primes and set of other primes they can pair with
return next(backtracking(prime_pairs, n), None)
Test Runs
for n, max_prime in [(2, 1000), (3, 1000), (4, 1000), (5, 9000)]:
print(find_groups(max_prime = max_prime, n = n))
Run Times
n max_prime Primes Found Run Time (secs)
2 1000 (3, 7) 0.1280
3 1000 (3, 37, 67) 0.1240
4 1000 (3, 7, 109, 673) 0.1233
5 40,000 (13, 5197, 5701, 6733, 8389) 7.1142
Note: Timings above performed on an older Windows desktop computer,
namely:
~7-year-old HP-Pavilion Desktop i7 CPU 920 # 2.67 GHz
I wrote this code based on an sieve of Eratosthenes which only stores the numbers 1 mod 6 and -1 mod 6. It is very fast.
def find_lowest_sum (pmax,num):
n=int(str(pmax)+str(pmax))
sieve5m6 = [True] * (n//6+1)
sieve1m6 = [True] * (n//6+1)
for i in range(1,int((n**0.5+1)/6)+1):
if sieve5m6[i]:
sieve5m6[6*i*i::6*i-1]=[False]*(((n//6+1)-6*i*i-1)//(6*i-1)+1)
sieve1m6[6*i*i-2*i::6*i-1]=[False]*(((n//6+1)-6*i*i+2*i-1)//(6*i-1)+1)
if sieve1m6[i]:
sieve5m6[6*i*i::6*i+1]=[False]*(((n//6+1)-6*i*i-1)//(6*i+1)+1)
sieve1m6[6*i*i+2*i::6*i+1]=[False]*(((n//6+1)-6*i*i-2*i-1)//(6*i+1)+1)
def test_concatenate (p1,p2):
ck=0
p3=int(str(p1)+str(p2))
if sieve1m6[(p3-1)//6] and p3%6==1:
ck=1
elif sieve5m6[(p3+1)//6]and p3%6==5:
ck=1
if ck==1:
p3=int(str(p2)+str(p1))
if sieve1m6[(p3-1)//6] and p3%6==1:
ck=2
elif sieve5m6[(p3+1)//6]and p3%6==5:
ck=2
if ck==2:
return True
else:
return False
kmax=(pmax+1)//6
s1=5*pmax
P1=[]
P2=[]
p=3
kmin=0
while p<s1//5:
if p==3 or(p%6==1 and sieve1m6[(p-1)//6])or(p%6==5 and sieve5m6[(p+1)//6]):
P=[]
if p%6==1:
kmin=p//6
elif p%6==5:
kmin=(p+1)//6
if sieve1m6[kmin]:
if test_concatenate(p,6*kmin+1):
P.append(6*kmin+1)
for k in range(kmin+1,kmax):
if sieve5m6[k]:
if test_concatenate(p,6*k-1):
P.append(6*k-1)
if sieve1m6[k]:
if test_concatenate(p,6*k+1):
P.append(6*k+1)
i1=0
while i1<len(P) and P[i1]<s1:
P1=[p]
s=p
P1.append(P[i1])
s+=P[i1]
for i2 in range(i1+1,len(P)):
for i3 in range(1,len(P1)):
ck=test_concatenate(P[i2],P1[i3])
if ck==False:
break
if len(P1)-1==i3 and ck==True:
P1.append(P[i2])
s+=P[i2]
if len(P1)==num:
if s<s1:
P2=P1
s1=s
break
i1+=1
p+=2
return P2
P=find_lowest_sum(9001,5)
print(P)
s=0
for i in range(0,len(P)):
s+=P[i]
print(s)

Fib2 function without recursion in Python

I need help for defining the fibanocci 2 function. The fibanocci 2 function is decribed as :
fib2(n) = {0 if n <= 0, 1 if n = 1, 2 if n = 2, ( fib2( n - 1) * fib2( n - 2)) - fib2( n - 3) else}
We need to define this function iterative.
I tried my best but i couldn't write a working code.
def fib2(n: int) -> int:
if n <= 0:
return 0
elif n == 1:
return 1
elif n == 2:
return 2
else:
n = ((n - 1) * (n - 2) - (n - 3)
return n
a = fib2(7)
print (a)
assert (fib2(7) == 37)
the output from this fib2 function is 26 but it should be 37.
Thank you in advance
For the iterative version you have to use a for loop.
And just add the 3 previous numbers to get the next one.
Here is a piece of code:
def fib3(n):
a = 0
b = 1
c = 0
for n in range(n):
newc = a+b+c
a = b
b = c
c = newc
return newc
print(fib3(7))
assert (fib3(7) == 37)
You can not change the value of a parameter.
Please try to return directly :
Return ((fb2(n-1)×fb2(n-2))-fb2(n-3))
So it will work as a recursive function.
def fibo(n):
current = 0
previous_1 = 1
previous_2 = 0
for i in range(1,n):
current = previous_1 + previous_2
previous_2 = previous_1
previous_1 = current
return current
To do it iteratively, the best way is to write it on paper to understand how it works.
Mathematically fibo is Fn = Fn-1 + Fn-2 . Therefore, you can create variables called previous_1 and previous_2 which represents the elements of Fn and you simply update them on each run.
Fn is current

Showing the 10 first prime Fibonacci numbers in python

There is a problem we need to solve in my university where we need to print the 10 smallest prime fibonacci numbers in an ascending order.So far i have found this code but it takes about 2 min to print them and was wondering if there was a faster way to print them.
import math
def isSquare(n):
sr = (int)(math.sqrt(n))
return (sr * sr == n)
def printPrimeAndFib(n):
prime = [True] * (n + 1)
p = 2
while (p * p <= n):
if (prime[p] == True):
for i in range(p * 2, n + 1, p):
prime[i] = False
p = p + 1
list=[]
for i in range(2, n + 1):
if (prime[i] and (isSquare(5 * i * i + 4) > 0 or
isSquare(5 * i * i - 4) > 0)):
list.append(i)
print(list)
n = 500000000
printPrimeAndFib(n)
With a Fibonacci generator and a prime filter. Takes about 0.002 seconds.
from itertools import islice
from math import isqrt
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
def is_prime(n):
return n > 1 and all(map(n.__mod__, range(2, isqrt(n) + 1)))
fibonacci_primes = filter(is_prime, fibonacci())
print(list(islice(fibonacci_primes, 10)))
Output:
[2, 3, 5, 13, 89, 233, 1597, 28657, 514229, 433494437]
This approach generates Fibonacci numbers until it finds 10 that are prime; takes approx 0.001-0.002 seconds
from math import sqrt
def isprime(x):
#deal with prime special cases 1 and 2
if x==2:
return True
if x == 1 or x%2==0:
return False
#Fast-ish prime checking - only scan odds numbers up to sqrt(x)
for n in range(3,int(sqrt(x))+1,2):
if x%n==0:
return False
return True
fib_primes = []
current=1
previous=1
while (len(fib_primes)<10):
if isprime(current):
fib_primes.append(current)
next = current+previous
previous = current
current = next
print(fib_primes)

Find how many combinations of integers possible to reach the result

I'm a bit stuck on a python problem.
I'm suppose to write a function that takes a positive integer n and returns the number of different operations that can sum to n (2<n<201) with decreasing and unique elements.
To give an example:
If n = 3 then f(n) = 1 (Because the only possible solution is 2+1).
If n = 5 then f(n) = 2 (because the possible solutions are 4+1 & 3+2).
If n = 10 then f(n) = 9 (Because the possible solutions are (9+1) & (8+2) & (7+3) & (7+2+1) & (6+4) & (6+3+1) & (5+4+1) & (5+3+2) & (4+3+2+1)).
For the code I started like that:
def solution(n):
nb = list(range(1,n))
l = 2
summ = 0
itt = 0
for index in range(len(nb)):
x = nb[-(index+1)]
if x > 3:
for index2 in range(x-1):
y = nb[index2]
#print(str(x) + ' + ' + str(y))
if (x + y) == n:
itt = itt + 1
for index3 in range(y-1):
z = nb[index3]
if (x + y + z) == n:
itt = itt + 1
for index4 in range(z-1):
w = nb[index4]
if (x + y + z + w) == n:
itt = itt + 1
return itt
It works when n is small but when you start to be around n=100, it's super slow and I will need to add more for loop which will worsen the situation...
Do you have an idea on how I could solve this issue? Is there an obvious solution I missed?
This problem is called integer partition into distinct parts. OEIS sequence (values are off by 1 because you don't need n=>n case )
I already have code for partition into k distinct parts, so modified it a bit to calculate number of partitions into any number of parts:
import functools
#functools.lru_cache(20000)
def diffparts(n, k, last):
result = 0
if n == 0 and k == 0:
result = 1
if n == 0 or k == 0:
return result
for i in range(last + 1, n // k + 1):
result += diffparts(n - i, k - 1, i)
return result
def dparts(n):
res = 0
k = 2
while k * (k + 1) <= 2 * n:
res += diffparts(n, k, 0)
k += 1
return res
print(dparts(201))

Categories