From 861327d463c8371bb96d6b32762265b1372353c3 Mon Sep 17 00:00:00 2001 From: Jaydeep Das Date: Sun, 28 Nov 2021 19:22:21 +0530 Subject: [PATCH 1/2] Added memoization function in fibonacci --- maths/fibonacci.py | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/maths/fibonacci.py b/maths/fibonacci.py index 9b193b74a827..cc37568c26b8 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -1,10 +1,10 @@ # fibonacci.py """ -Calculates the Fibonacci sequence using iteration, recursion, and a simplified -form of Binet's formula +Calculates the Fibonacci sequence using iteration, recursion, memoization, +and a simplified form of Binet's formula -NOTE 1: the iterative and recursive functions are more accurate than the Binet's -formula function because the iterative function doesn't use floats +NOTE 1: the iterative, recursive, memoization functions are more accurate than +the Binet's formula function because the iterative function doesn't use floats NOTE 2: the Binet's formula function is much more limited in the size of inputs that it can handle due to the size limitations of Python floats @@ -12,6 +12,7 @@ from math import sqrt from time import time +from typing import Callable def time_func(func, *args, **kwargs): @@ -86,6 +87,35 @@ def fib_recursive_term(i: int) -> int: return [fib_recursive_term(i) for i in range(n + 1)] +def fib_memoization() -> Callable[[int], int]: + """ + Calculates the nth fibonacci number using Memoization + >>> fib_memoization()(5) + 5 + >>> fib_memoization()(100) + 354224848179261915075 + >>> fib_memoization()(25) + 75025 + >>> fib_memoization()(40) + 102334155 + """ + # Cache must be outside recursuive function + # other it will reset every time it calls itself. + cache: dict[int, int] = {1: 1, 2: 1} # Prefilled cache + + def rec_fn_memoized(num: int) -> int: + if num < 1: + raise Exception("n is negative") + if num in cache: + return cache[num] + + value = rec_fn_memoized(num - 1) + rec_fn_memoized(num - 2) + cache[num] = value + return value + + return rec_fn_memoized + + def fib_binet(n: int) -> list[int]: """ Calculates the first n (0-indexed) Fibonacci numbers using a simplified form @@ -127,4 +157,5 @@ def fib_binet(n: int) -> list[int]: num = 20 time_func(fib_iterative, num) time_func(fib_recursive, num) + time_func(fib_memoization(), num) time_func(fib_binet, num) From 63164d936b661d7a6f9273763ec9f73751b9b707 Mon Sep 17 00:00:00 2001 From: Jaydeep Das Date: Sun, 28 Nov 2021 22:06:06 +0530 Subject: [PATCH 2/2] Minor changes --- maths/fibonacci.py | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/maths/fibonacci.py b/maths/fibonacci.py index cc37568c26b8..ca4f4a2360a3 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -4,15 +4,20 @@ and a simplified form of Binet's formula NOTE 1: the iterative, recursive, memoization functions are more accurate than -the Binet's formula function because the iterative function doesn't use floats +the Binet's formula function because the Binet formula function uses floats NOTE 2: the Binet's formula function is much more limited in the size of inputs that it can handle due to the size limitations of Python floats + +RESULTS: (n = 20) +fib_iterative runtime: 0.0055 ms +fib_recursive runtime: 6.5627 ms +fib_memoization runtime: 0.0107 ms +fib_binet runtime: 0.0174 ms """ from math import sqrt from time import time -from typing import Callable def time_func(func, *args, **kwargs): @@ -87,25 +92,29 @@ def fib_recursive_term(i: int) -> int: return [fib_recursive_term(i) for i in range(n + 1)] -def fib_memoization() -> Callable[[int], int]: +def fib_memoization(n: int) -> list[int]: """ - Calculates the nth fibonacci number using Memoization - >>> fib_memoization()(5) - 5 - >>> fib_memoization()(100) - 354224848179261915075 - >>> fib_memoization()(25) - 75025 - >>> fib_memoization()(40) - 102334155 + Calculates the first n (0-indexed) Fibonacci numbers using memoization + >>> fib_memoization(0) + [0] + >>> fib_memoization(1) + [0, 1] + >>> fib_memoization(5) + [0, 1, 1, 2, 3, 5] + >>> fib_memoization(10) + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + >>> fib_iterative(-1) + Traceback (most recent call last): + ... + Exception: n is negative """ + if n < 0: + raise Exception("n is negative") # Cache must be outside recursuive function # other it will reset every time it calls itself. - cache: dict[int, int] = {1: 1, 2: 1} # Prefilled cache + cache: dict[int, int] = {0: 0, 1: 1, 2: 1} # Prefilled cache def rec_fn_memoized(num: int) -> int: - if num < 1: - raise Exception("n is negative") if num in cache: return cache[num] @@ -113,7 +122,7 @@ def rec_fn_memoized(num: int) -> int: cache[num] = value return value - return rec_fn_memoized + return [rec_fn_memoized(i) for i in range(n + 1)] def fib_binet(n: int) -> list[int]: @@ -157,5 +166,5 @@ def fib_binet(n: int) -> list[int]: num = 20 time_func(fib_iterative, num) time_func(fib_recursive, num) - time_func(fib_memoization(), num) + time_func(fib_memoization, num) time_func(fib_binet, num)