From 2a513f02c2688b15b1feed64d02c7b2476e4f594 Mon Sep 17 00:00:00 2001 From: "mahbubur.rahman" Date: Fri, 19 Jul 2019 11:59:37 +0900 Subject: [PATCH 1/4] Added matrix exponentiation approach for finding fibonacci number. * Implemented the way of finding nth fibonacci. * Complexity is about O(log(n)*8) --- ..._fibonnacci_using_matrix_exponentiation.py | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 matrix/nth_fibonnacci_using_matrix_exponentiation.py diff --git a/matrix/nth_fibonnacci_using_matrix_exponentiation.py b/matrix/nth_fibonnacci_using_matrix_exponentiation.py new file mode 100644 index 000000000000..5072da8f8333 --- /dev/null +++ b/matrix/nth_fibonnacci_using_matrix_exponentiation.py @@ -0,0 +1,98 @@ +""" +Implementation of finding nth fibonacci number using matrix exponentiation. +Time Complexity is about O(log(n)*8) +As we know + f[n] = f[n-1] + f[n-1] +Converting to matrix, + [f(n),f(n-1)] = [[1,1],[1,0]] * [f(n-1),f(n-2)] +-> [f(n),f(n-1)] = [[1,1],[1,0]]^2 * [f(n-2),f(n-3)] + ... + ... +-> [f(n),f(n-1)] = [[1,1],[1,0]]^(n-1) * [f(1),f(0)] + +So we just need the n times multiplication of the matrix [1,1],[1,0]]. +We can decrease the n times multiplication by following the divide and conquer approach + +""" +from __future__ import print_function + + +def multiply(matrix_a, matrix_b): + matrix_c = [] + n = len(matrix_a) + for i in range(n): + list_1 = [] + for j in range(n): + val = 0 + for k in range(n): + val = val + matrix_a[i][k] * matrix_b[k][j] + list_1.append(val) + matrix_c.append(list_1) + return matrix_c + + +def identity(n): + return [[int(row == column) for column in range(n)] for row in range(n)] + + +def zerro(n): + return [[int(row == column) for column in range(n)] for row in range(n)] + + +def nth_fibonacci(n): + if n <= 1: + return n + res_matrix = identity(2) + fibonacci_matrix = [[1, 1], [1, 0]] + n = n - 1 + while n > 0: + if n % 2 == 1: + res_matrix = multiply(res_matrix, fibonacci_matrix) + fibonacci_matrix = multiply(fibonacci_matrix, fibonacci_matrix) + n = int(n / 2) + return res_matrix[0][0] + + +def nth_fibonnaci_test(n): + if n <= 1: + return n + fib0 = 0 + fib1 = 1 + for i in range(2, n + 1): + fib0, fib1 = fib1, fib0 + fib1 + return fib1 + + +def main(): + print( + "0th fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(0), nth_fibonnaci_test(0)) + ) + print( + "1st fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(1), nth_fibonnaci_test(1)) + ) + print( + "2nd fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(2), nth_fibonnaci_test(2)) + ) + print( + "3rd fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(3), nth_fibonnaci_test(3)) + ) + print( + "10th fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(10), nth_fibonnaci_test(10)) + ) + print( + "100th fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(100), nth_fibonnaci_test(100)) + ) + print( + "1000th fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(1000), nth_fibonnaci_test(1000)) + ) + + +if __name__ == "__main__": + main() From b159705b6d7b33063bb09af8a6b1397766e8b050 Mon Sep 17 00:00:00 2001 From: "Md. Mahbubur Rahman" Date: Fri, 19 Jul 2019 14:56:39 +0900 Subject: [PATCH 2/4] Updated the matrix exponentiation approach of finding nth fibonacci. - Removed some extra spaces - Added the complexity of bruteforce algorithm - Removed unused function called zerro() - Added some docktest based on request --- ..._fibonacci_using_matrix_exponentiation.py} | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) rename matrix/{nth_fibonnacci_using_matrix_exponentiation.py => nth_fibonacci_using_matrix_exponentiation.py} (57%) diff --git a/matrix/nth_fibonnacci_using_matrix_exponentiation.py b/matrix/nth_fibonacci_using_matrix_exponentiation.py similarity index 57% rename from matrix/nth_fibonnacci_using_matrix_exponentiation.py rename to matrix/nth_fibonacci_using_matrix_exponentiation.py index 5072da8f8333..fd9e0cba38a4 100644 --- a/matrix/nth_fibonnacci_using_matrix_exponentiation.py +++ b/matrix/nth_fibonacci_using_matrix_exponentiation.py @@ -1,6 +1,7 @@ """ Implementation of finding nth fibonacci number using matrix exponentiation. -Time Complexity is about O(log(n)*8) +Time Complexity is about O(log(n)*8), where 8 is the complexity of matrix multiplication of size 2 by 2. +And on the other hand complexity of bruteforce solution is O(n). As we know f[n] = f[n-1] + f[n-1] Converting to matrix, @@ -9,9 +10,8 @@ ... ... -> [f(n),f(n-1)] = [[1,1],[1,0]]^(n-1) * [f(1),f(0)] - So we just need the n times multiplication of the matrix [1,1],[1,0]]. -We can decrease the n times multiplication by following the divide and conquer approach +We can decrease the n times multiplication by following the divide and conquer approach. """ from __future__ import print_function @@ -35,11 +35,13 @@ def identity(n): return [[int(row == column) for column in range(n)] for row in range(n)] -def zerro(n): - return [[int(row == column) for column in range(n)] for row in range(n)] - - def nth_fibonacci(n): + """ + >>> nth_fibonacci(100) + 354224848179261915075L + >>> nth_fibonacci(-100) + -100 + """ if n <= 1: return n res_matrix = identity(2) @@ -53,7 +55,7 @@ def nth_fibonacci(n): return res_matrix[0][0] -def nth_fibonnaci_test(n): +def nth_fibonacci_test(n): if n <= 1: return n fib0 = 0 @@ -65,32 +67,32 @@ def nth_fibonnaci_test(n): def main(): print( - "0th fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(0), nth_fibonnaci_test(0)) + "0th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(0), nth_fibonacci_test(0)) ) print( - "1st fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(1), nth_fibonnaci_test(1)) + "1st fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(1), nth_fibonacci_test(1)) ) print( - "2nd fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(2), nth_fibonnaci_test(2)) + "2nd fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(2), nth_fibonacci_test(2)) ) print( - "3rd fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(3), nth_fibonnaci_test(3)) + "3rd fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(3), nth_fibonacci_test(3)) ) print( - "10th fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(10), nth_fibonnaci_test(10)) + "10th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(10), nth_fibonacci_test(10)) ) print( - "100th fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(100), nth_fibonnaci_test(100)) + "100th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(100), nth_fibonacci_test(100)) ) print( - "1000th fibonnacsi number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(1000), nth_fibonnaci_test(1000)) + "1000th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" + % (nth_fibonacci(1000), nth_fibonacci_test(1000)) ) From 044cca8253a71b958fbbf6601c27fdbfe15d73c2 Mon Sep 17 00:00:00 2001 From: "Md. Mahbubur Rahman" Date: Fri, 19 Jul 2019 15:05:27 +0900 Subject: [PATCH 3/4] Updated the matrix exponentiation approach of finding nth fibonacci. - Removed some extra spaces - Added the complexity of bruteforce algorithm - Removed unused function called zerro() - Added some docktest based on request --- ...h_fibonacci_using_matrix_exponentiation.py | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/matrix/nth_fibonacci_using_matrix_exponentiation.py b/matrix/nth_fibonacci_using_matrix_exponentiation.py index fd9e0cba38a4..2904379ca7d5 100644 --- a/matrix/nth_fibonacci_using_matrix_exponentiation.py +++ b/matrix/nth_fibonacci_using_matrix_exponentiation.py @@ -10,9 +10,8 @@ ... ... -> [f(n),f(n-1)] = [[1,1],[1,0]]^(n-1) * [f(1),f(0)] -So we just need the n times multiplication of the matrix [1,1],[1,0]]. -We can decrease the n times multiplication by following the divide and conquer approach. - +So we just need the n times multiplication of the matrix [1,1],[1,0]]. +We can decrease the n times multiplication by following the divide and conquer approach. """ from __future__ import print_function @@ -35,11 +34,11 @@ def identity(n): return [[int(row == column) for column in range(n)] for row in range(n)] -def nth_fibonacci(n): +def nth_fibonacci_matrix(n): """ - >>> nth_fibonacci(100) - 354224848179261915075L - >>> nth_fibonacci(-100) + >>> nth_fibonacci_matrix(100) + 354224848179261915075 + >>> nth_fibonacci_matrix(-100) -100 """ if n <= 1: @@ -55,7 +54,13 @@ def nth_fibonacci(n): return res_matrix[0][0] -def nth_fibonacci_test(n): +def nth_fibonacci_bruteforce(n): + """ + >>> nth_fibonacci_bruteforce(100) + 354224848179261915075 + >>> nth_fibonacci_bruteforce(-100) + -100 + """ if n <= 1: return n fib0 = 0 @@ -68,31 +73,31 @@ def nth_fibonacci_test(n): def main(): print( "0th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(0), nth_fibonacci_test(0)) + % (nth_fibonacci_matrix(0), nth_fibonacci_bruteforce(0)) ) print( "1st fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(1), nth_fibonacci_test(1)) + % (nth_fibonacci_matrix(1), nth_fibonacci_bruteforce(1)) ) print( "2nd fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(2), nth_fibonacci_test(2)) + % (nth_fibonacci_matrix(2), nth_fibonacci_bruteforce(2)) ) print( "3rd fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(3), nth_fibonacci_test(3)) + % (nth_fibonacci_matrix(3), nth_fibonacci_bruteforce(3)) ) print( "10th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(10), nth_fibonacci_test(10)) + % (nth_fibonacci_matrix(10), nth_fibonacci_bruteforce(10)) ) print( "100th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(100), nth_fibonacci_test(100)) + % (nth_fibonacci_matrix(100), nth_fibonacci_bruteforce(100)) ) print( "1000th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci(1000), nth_fibonacci_test(1000)) + % (nth_fibonacci_matrix(1000), nth_fibonacci_bruteforce(1000)) ) From 8e5481d179ac106a769247fecd03f7cbddbd11c6 Mon Sep 17 00:00:00 2001 From: cclauss Date: Fri, 19 Jul 2019 09:41:04 +0200 Subject: [PATCH 4/4] Tighten up main() and add comments on performance --- ...h_fibonacci_using_matrix_exponentiation.py | 39 ++++++------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/matrix/nth_fibonacci_using_matrix_exponentiation.py b/matrix/nth_fibonacci_using_matrix_exponentiation.py index 2904379ca7d5..cee6b21c81eb 100644 --- a/matrix/nth_fibonacci_using_matrix_exponentiation.py +++ b/matrix/nth_fibonacci_using_matrix_exponentiation.py @@ -71,34 +71,17 @@ def nth_fibonacci_bruteforce(n): def main(): - print( - "0th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci_matrix(0), nth_fibonacci_bruteforce(0)) - ) - print( - "1st fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci_matrix(1), nth_fibonacci_bruteforce(1)) - ) - print( - "2nd fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci_matrix(2), nth_fibonacci_bruteforce(2)) - ) - print( - "3rd fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci_matrix(3), nth_fibonacci_bruteforce(3)) - ) - print( - "10th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci_matrix(10), nth_fibonacci_bruteforce(10)) - ) - print( - "100th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci_matrix(100), nth_fibonacci_bruteforce(100)) - ) - print( - "1000th fibonacci number using matrix exponentiation is %s and using bruteforce is %s \n" - % (nth_fibonacci_matrix(1000), nth_fibonacci_bruteforce(1000)) - ) + fmt = "{} fibonacci number using matrix exponentiation is {} and using bruteforce is {}\n" + for ordinal in "0th 1st 2nd 3rd 10th 100th 1000th".split(): + n = int("".join(c for c in ordinal if c in "0123456789")) # 1000th --> 1000 + print(fmt.format(ordinal, nth_fibonacci(n), nth_fibonacci_test(n))) + # from timeit import timeit + # print(timeit("nth_fibonacci_matrix(1000000)", + # "from main import nth_fibonacci_matrix", number=5)) + # print(timeit("nth_fibonacci_bruteforce(1000000)", + # "from main import nth_fibonacci_bruteforce", number=5)) + # 2.3342058970001744 + # 57.256506615000035 if __name__ == "__main__":