Python: Compute a Huge Fibonacci Number Modulo m - python-3.x

# Uses python3
# Given two integers n and m, output Fn mod m (that is, the remainder of Fn when divided by m
def Huge_Fib(n,m):
if n == 0 : return 0
elif n == 1: return 1
else:
a,b = 0,1
for i in range(1,n):
a, b = b, (a+b) % m
print(b);
n,m = map(int, input().split());
Huge_Fib(n,m);
The code works very well. However, when I run a case as n = 99999999999999999, m = 2, it takes me much time. Do you have any better solutions?

Here is my solution, you don't have to go through 99999999999999999 iterations if you find the pisano period.
I also recommend that you watch this video: https://www.youtube.com/watch?v=Nu-lW-Ifyec
# Uses python3
import sys
def get_fibonacci_huge(n, m):
if n <= 1:
return n
arr = [0, 1]
previousMod = 0
currentMod = 1
for i in range(n - 1):
tempMod = previousMod
previousMod = currentMod % m
currentMod = (tempMod + currentMod) % m
arr.append(currentMod)
if currentMod == 1 and previousMod == 0:
index = (n % (i + 1))
return arr[index]
return currentMod
if __name__ == '__main__':
input = sys.stdin.read();
n, m = map(int, input.split())
print(get_fibonacci_huge(n,m))

# Uses python3
# Given two integers n and m, output Fn mod m (that is, the remainder of Fn when divided by m
def Huge_Fib(n,m):
# Initialize a matrix [[1,1],[1,0]]
v1, v2, v3 = 1, 1, 0
# Perform fast exponentiation of the matrix (quickly raise it to the nth power)
for rec in bin(n)[3:]:
calc = (v2*v2) % m
v1, v2, v3 = (v1*v1+calc) % m, ((v1+v3)*v2) % m, (calc+v3*v3) % m
if rec == '1': v1, v2, v3 = (v1+v2) % m, v1, v2
print(v2);
n,m = map(int, input().split());
Huge_Fib(n,m);
This is a superfast solution refer to https://stackoverflow.com/a/23462371/3700852

I solved it in Python 3. This the fastest algorithm to compute a huge Fibonacci number modulo m.For example for n =2816213588, m = 239, it took Max time used: 0.01/5.00, max memory used: 9424896/536870912.)
def pisanoPeriod(m):
previous, current = 0, 1
for i in range(0, m * m):
previous, current = current, (previous + current) % m
# A Pisano Period starts with 01
if (previous == 0 and current == 1):
return i + 1
def calc_fib(n,m):
p = pisanoPeriod(m)
n = n % p
if (n <= 1):
return n
else:
previous,current = 0,1
for i in range(2,n+1):
previous,current = current,(previous+current)
return current%m
n,m =map(int,input().split(" "))
print(calc_fib(n,m))

In the below code we are using two concepts of Fibonacci series:
Pisano periods follows a Fibonacci sequence and hence each repetition(pattern) begins with 0 and 1 appearing consecutively one after the other.
fib(n) divides fib(m) only when n divides m which means if fib(4)%3==0,then fib(4+4)%3==0,fib(4+4+4)%3==0 and so on.This helps us in finding the Pisano period.
To know about Pisano periods,I recommend that you watch this video: https://www.youtube.com/watch?v=Nu-lW-Ifyec
#python3
def pisano_length(m):
i=2
while(fib(i)%m!=0):
i+=1
if(fib(i+1)%m!=1):
while(fib(i+1)%m!=1):
i+=i
print("The pisano length for mod {} is: {}".format(m,i))
return(i)
def fib(n):
a,b=0,1
if(n==0 or n==1):
return n
else:
for i in range(2,n+1):
b,a=a+b,b
return(b)
#we want to calculate fib(n)%m for big numbers
n,m=map(int,input().split())
remainder=n%pisano_length(m)
print(fib(remainder)%m)

You should look up Pisano periods.
https://en.wikipedia.org/wiki/Pisano_period and
http://webspace.ship.edu/msrenault/fibonacci/fibfactory.htm should give you a good understanding of what they are.
edit: Just googling "fibonacci modulo" gives you those two as the top two results.

For any integer m>=2, the sequence fn modulo m is periodic - Pisano Period.
So no need to store and find fn. Instead, find a repeating pattern for given m.

This is how i have done by calculating the pisano period.(Java)
public static long get_pisano_period(long m) {
long a = 0, b = 1;
long c;
for (int i = 0; i < m * m; i++) {
c = (a + b) % m;
a = b;
b = c;
if (a == 0 && b == 1)
return i + 1;
}
return 0;
}
public static BigInteger get_fibonacci_huge(long n,long m) {
long remainder = n % get_pisano_period(m);
BigInteger first = BigInteger.valueOf(0);
BigInteger second=BigInteger.valueOf(1);
BigInteger m1=BigInteger.valueOf(m);
BigInteger res = BigInteger.valueOf(remainder);
for (long i = 1; i < remainder; i++) {
res = (first.add(second)).mod(m1);
first = second;
second = res;
}
return res.mod(m1);
}

Related

Codewars challenge solution is too slow

The challenge is like so:
Your task is to construct a building which will be a pile of n cubes. The cube at the bottom will have a volume of n3 n^3 n3, the cube above will have volume of (n−1)3 (n-1)^3 (n−1)3 and so on until the top which will have a volume of 13 1^3 13.
You are given the total volume m of the building. Being given m can you find the number n of cubes you will have to build?
The parameter of the function findNb (find_nb, find-nb, findNb, ...) will be an integer m and you have to return the integer n such as n3+(n−1)3+(n−2)3+...+13=m n^3 + (n-1)^3 + (n-2)^3 + ... + 1^3 = m n3+(n−1)3+(n−2)3+...+13=m if such a n exists or -1 if there is no such n.
Examples:
findNb(1071225) --> 45
findNb(91716553919377) --> -1
I have solved as follows, but its too slow. Is there a way to make it faster?
def find_nb(m):
n = 0
x = 0
while x < m:
n += 1
x = sum([(n-i)**3 for i in range(n)])
if x == m:
return n
else:
continue
return -1
print(find_nb(135440716410000))
You can use this by python:
def findNb(m):
n = 0
while m > 0:
n += 1
m -= n**3
return n if m == 0 else -1

Maximum sum of contiguous sub-sequence with length at most k

I am trying to modify the Kadane Algorithm in order to solve a more specific problem.
def max_Sum(arr, length, k):
if length < k:
print('length of array should be greater than k')
res = 0
for i in range(0, k):
res += arr[i]
current_sum = res
for i in range(k, n):
if k == n:
for j in range(0, k-1):
res += arr[j]
current_sum = res
else:
current_sum += arr[i] - arr[i-k]
print(res, current_sum)
res = max(res, current_sum)
return res
This is the code for the maximum subarray problem. What I want to do is find the maximum subarray with length at most K.
Example: We have an array A = [3,-5 1 2,-1 4,-3 1,-2] and we want to find the maximum subarray of length at most K = 9. Length of subarray should not be restricted at K, if there is another length L < K that provides a greater sum, the algorithm should return sum[:L].
In this case, the algorithm will return 0. It should return 6, following the sum of A[2:5].
Well, a solution that works in O(n * K) is to use sliding windows for every possible length <= K. I have tried to find a O(n) correct solution modifying Kadane, but I couldn't.
def best_array_fixed_k( arr, length, k ):
total_sum = 0
best = 0
for x in xrange( 0, length ):
total_sum = total_sum + arr[x]
if x >= k:
total_sum = total_sum - arr[x - k]
if x >= k - 1:
best = max( best, total_sum )
# this makes sure that we are considering a window with length = k
return best
def max_sum( arr, length, k):
best = 0
for x in xrange( 1, k + 1):
best = max( best, best_array_for_fixed_k(arr, length, x ) )
return best
For those who are seeking an answer in O(n), you can easily adapt the answer to this question over at CS StackExchange. The answer solves the same problem in O(n) where subsequence's length must be in a given range. For this problem, just set the range to [0, k].
Solution in java with time complexity : O(n*k)
public static int maxSumforFixedSizeK(int[] arr, int k){
// Using simple window sliding technique
int best_sum;
int curr_sum=0;
for( int i=0;i<k;i++)
curr_sum += arr[i];
best_sum = curr_sum;
for( int i=k; i<arr.length; i++) {
curr_sum += (arr[i] - arr[i - k]);
best_sum = Math.max(best_sum, curr_sum);
}
return best_sum;
}
public static int maxSumforSizeAtMostK(int[] arr, int k){
int best_sum = Integer.MIN_VALUE;
// Calculate maximum sum for every window size in interval [1,k]
for( int i=1; i<=k; i++ )
best_sum = Math.max( best_sum, maxSumforFixedSizeK(arr, i) );
return best_sum;
}

Length of the factorial

I tried running the program below:
from functools import lru_cache
#lru_cache(Maxsize = None)
def count(n):
factorial_num = 1
num_digits = 0
if n == 1:
factorial_num = 1
else:
factorial_num = n * count(n-1)
return len(str(factorial_num))
However, it didn't give me the length of the factorial number as anticipated.
I also wanted to use the code to find the factorial of very big numbers in range of billions and tried using lru_cache. Still, no luck.
As Aziz pointed out in the comments, your recursive case is wrong.
factorial_num = n * count(n-1)
This would do something useful if count(n-1) actually returned (n-1)!, but it doesn't, since you're trying to return a digit count instead.
>>> count(1)
1 # Base case is correct.
>>> count(2)
1 # 2 * count(1) = 2 * 1 = 2. Whose *length* is 1 digit.
>>> count(9)
1 # For all single-digit n, count(n) is still 1.
>>> count(10)
2 # 10 * count(9) = 10 * 1 = 10. Whose *length* is 2 digits.
You should write a function that just calculates the factorial, instead of trying to mix this logic with the digit counting.
#lru_cache(maxsize=None)
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n - 1)
Note that recent versions of Python have a built-in math.factorial function, which you could use instead if your teacher is not requiring you to roll your own factorial code.
Then, you can simply use len(str(factorial(n))) to count the digits.
You can use Kamenetsky formula to return the number of digits in n!
For minor numbers use:
def findDigits(n):
if (n < 0):
return 0;
if (n <= 1):
return 1;
digits = 0;
for i in range(2, n + 1):
digits += math.log10(i);
return math.floor(digits) + 1;
For bigger numbers use:
def findDigits(n):
if (n < 0):
return 0;
if (n <= 1):
return 1;
x = ((n * math.log10(n / math.e) +
math.log10(2 * math.pi * n) /2.0));
return math.floor(x) + 1;
source: https://www.geeksforgeeks.org/count-digits-factorial-set-1/?ref=lbp and https://www.geeksforgeeks.org/count-digits-factorial-set-2/?ref=lbp

How to write cos(1)

I need to find a way to write cos(1) in python using a while loop. But i cant use any math functions. Can someone help me out?
for example I also had to write the value of exp(1) and I was able to do it by writing:
count = 1
term = 1
expTotal = 0
xx = 1
while abs(term) > 1e-20:
print("%1d %22.17e" % (count, term))
expTotal = expTotal + term
term=term * xx/(count)
count+=1
I amm completely lost as for how to do this with the cos and sin values though.
Just change your expression to compute the term to:
term = term * (-1 * x * x)/( (2*count) * ((2*count)-1) )
Multiplying the count by 2 could be changed to increment the count by 2, so here is your copypasta:
import math
def cos(x):
cosTotal = 1
count = 2
term = 1
x=float(x)
while abs(term) > 1e-20:
term *= (-x * x)/( count * (count-1) )
cosTotal += term
count += 2
print("%1d %22.17e" % (count, term))
return cosTotal
print( cos(1) )
print( math.cos(1) )
You can calculate cos(1) by using the Taylor expansion of this function:
You can find more details on Wikipedia, see an implementation below:
import math
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
def cos(order):
a = 0
for i in range(0, order):
a += ((-1)**i)/(factorial(2*i)*1.0)
return a
print cos(10)
print math.cos(1)
This gives as output:
0.540302305868
0.540302305868
EDIT: Apparently the cosine is implemented in hardware using the CORDIC algorithm that uses a lookup table to calculate atan. See below a Python implementation of the CORDIS algorithm based on this Google group question:
#atans = [math.atan(2.0**(-i)) for i in range(0,40)]
atans =[0.7853981633974483, 0.4636476090008061, 0.24497866312686414, 0.12435499454676144, 0.06241880999595735, 0.031239833430268277, 0.015623728620476831, 0.007812341060101111, 0.0039062301319669718, 0.0019531225164788188, 0.0009765621895593195, 0.0004882812111948983, 0.00024414062014936177, 0.00012207031189367021, 6.103515617420877e-05, 3.0517578115526096e-05, 1.5258789061315762e-05, 7.62939453110197e-06, 3.814697265606496e-06, 1.907348632810187e-06, 9.536743164059608e-07, 4.7683715820308884e-07, 2.3841857910155797e-07, 1.1920928955078068e-07, 5.960464477539055e-08, 2.9802322387695303e-08, 1.4901161193847655e-08, 7.450580596923828e-09, 3.725290298461914e-09, 1.862645149230957e-09, 9.313225746154785e-10, 4.656612873077393e-10, 2.3283064365386963e-10, 1.1641532182693481e-10, 5.820766091346741e-11, 2.9103830456733704e-11, 1.4551915228366852e-11, 7.275957614183426e-12, 3.637978807091713e-12, 1.8189894035458565e-12]
def cosine_sine_cordic(beta,N=40):
# in hardware, put this in a table.
def K_vals(n):
K = []
acc = 1.0
for i in range(0, n):
acc = acc * (1.0/(1 + 2.0**(-2*i))**0.5)
K.append(acc)
return K
#K = K_vals(N)
K = 0.6072529350088812561694
x = 1
y = 0
for i in range(0,N):
d = 1.0
if beta < 0:
d = -1.0
(x,y) = (x - (d*(2.0**(-i))*y), (d*(2.0**(-i))*x) + y)
# in hardware put the atan values in a table
beta = beta - (d*atans[i])
return (K*x, K*y)
if __name__ == '__main__':
beta = 1
cos_val, sin_val = cosine_sine_cordic(beta)
print "Actual cos: " + str(math.cos(beta))
print "Cordic cos: " + str(cos_val)
This gives as output:
Actual cos: 0.540302305868
Cordic cos: 0.540302305869

Is there a way to speed up this function?

I'm comparing performance of this F# function:
let e28 N =
seq {for i in 2L..2L..N do for j in 1..4 -> i} |> Seq.scan (+) 1L |> Seq.sum
with Python 3.3 equivalents:
def e28a(N = 100000):
diagNumber = 1
sum = diagNumber
for width in range(2, N+1, 2):
for j in range(4):
diagNumber += width
sum += diagNumber
return sum
import itertools as it
def e28b(N = 100000):
return sum(it.accumulate(it.chain([1], (i for i in range(2, N+1, 2) for j in range(4)))))
import numpy as np
def e28c(N = 100000):
return np.sum(np.cumsum(np.fromiter(chain([1], (i for i in range(2, N+1, 2) for j in range(4))), np.int64)))
and I'm getting 64-bit CPython 3.3.1 performance on Windows 7 about 574 times slower than C++. Here are the times for N = 100000:
e28: 23ms; e28a: 48.4ms; e28b: 49.7ms; e28c: 40.2ms; C++ version: 0.07ms
Is there a low hanging fruit in optimizing Python code without altering the underlying algorithm?
The F# version can be sped up by ~10x by switching to a procedural, mutable approach (like your python e28a). When the "payload operation" (in this case, just +) is so trivial, the use of combinators ends up adding a relatively significant overhead. As a side note, Seq.sum uses checked arithmetic, which also adds a touch of overhead.
One of the nice things about F# is that you can fall back to procedural/mutable style if needed for a perf-critical hot path.
let e28_original N =
seq {
for i in 2UL..2UL..N do
for j in 1..4 do
yield i
}
|> Seq.scan (+) 1UL
|> Seq.sum
let e28_mutable N =
let mutable sum = 1UL
let mutable total = sum
for i in 2UL..2UL..N do
for j in 1..4 do
sum <- sum + i
total <- total + sum
total
let time f =
f () |> ignore // allow for warmup / JIT
let sw = System.Diagnostics.Stopwatch.StartNew()
let result = f ()
sw.Stop()
printfn "Result: %A Elapsed: %A" result sw.Elapsed
time (fun _ -> e28_original 100000UL)
time (fun _ -> e28_mutable 100000UL)
Result
Result: 666691667100001UL Elapsed: 00:00:00.0429414
Result: 666691667100001UL Elapsed: 00:00:00.0034971
Using your F# version I got:
> e28(100000L);;
Real: 00:00:00.061, CPU: 00:00:00.062, GC gen0: 2, gen1: 0, gen2: 0
val it : int64 = 666691667100001L
Using:
let e28d N =
seq {2L..2L..N}
|> Seq.collect(fun x->seq{yield x;yield x; yield x; yield x})
|> Seq.scan (+) 1L
|> Seq.sum
I got:
> e28d(100000L);;
Real: 00:00:00.040, CPU: 00:00:00.031, GC gen0: 2, gen1: 0, gen2: 0
val it : int64 = 666691667100001L
You will probably have a difficult time getting the python to perform quite as well as the F# simply since F# is compiled and Python is interpreted. That being said, the above improvement will work for the python as well:
>>> def e28a(N = 100000):
diagNumber = 1;
sum = diagNumber;
for width in range(2, N+1, 2):
for j in range(4):
diagNumber += width;
sum += diagNumber;
return sum;
>>> if __name__ == '__main__':
import timeit
print(timeit.timeit("e28a()", setup="from __main__ import e28a", number=10))
0.5249497228663813
>>> def e28a(N = 100000):
diagNumber = 1;
sum = diagNumber;
for width in range(2, N+1, 2):
diagNumber += width;
sum += diagNumber;
diagNumber += width;
sum += diagNumber;
diagNumber += width;
sum += diagNumber;
diagNumber += width;
sum += diagNumber;
return sum;
>>> if __name__ == '__main__':
import timeit
print(timeit.timeit("e28a()", setup="from __main__ import e28a", number=10))
0.2585966329330063
>>>
Part of this improvement comes from fewer function calls, i.e.:
>>> def e28a(N = 100000):
diagNumber = 1;
sum = diagNumber;
temp_range = range(4) #Change here
for width in range(2, N+1, 2):
for j in temp_range: #Change here
diagNumber += width;
sum += diagNumber;
return sum;
>>> if __name__ == '__main__':
import timeit
print(timeit.timeit("e28a()", setup="from __main__ import e28a", number=10))
0.40251470339956086
>>>
And I think the other part comes from removing the loop. Both of these can be fairly expensive in Python.
This is almost twice as fast on my machine. It uses memoization, and also basic arithmetic deduction.
You have to define a global variable.
summi=2
def e28d(N = 100000):
def memo(width):
global summi
summi+=width*4+4
return summi-width*2+2
x= sum((memo(width*4)) for width in range (2, N+1, 2))+1
return x
Results:
e28a:
0.0591201782227 seconds
e28d:
0.0349650382996 seconds
Hope it is at least constructive. Note: you would have to modulate it according to whether the number is odd or not.
Update:
Here is a function that runs about a hundred times faster in python (about 0.5 ms for N=100000), by avoiding loops totally:
import math
def e28e(X = 100000):
keyint, keybool=int(X/6), X%6
if keybool/2==0: keyvar=(16*keyint+sum(range(keyint))*12)
elif keybool/2==1: keyvar=(44*keyint+sum(range(keyint))*36+7)
else: keyvar=(28*(keyint+1)+sum(range(keyint+1))*60-2)
X-=keybool%2
diag= math.pow(X,2)+2*X+1
newvar=keyint+int(X/2)+1
summ= int(diag*newvar+keyvar)
return summ

Resources