# fibonacci.pyfrom math import sqrt
from time import time
deftime_func(func,*args,**kwargs):
start = time()
output = func(*args,**kwargs)
end = time()ifint(end - start)>0:print(f"{func.__name__} runtime: {(end - start):0.4f} s")else:print(f"{func.__name__} runtime: {(end - start)*1000:0.4f} ms")return output
deffib_iterative(n:int)->list[int]:if n <0:raise Exception("n is negative")if n ==0:return[0]
fib =[0,1]for _ inrange(n -1):
fib.append(fib[-1]+ fib[-2])return fib
deffib_recursive(n:int)->list[int]:deffib_recursive_term(i:int)->int:"""
Calculates the i-th (0-indexed) Fibonacci number using recursion
"""if i <0:raise Exception("n is negative")if i <2:return i
return fib_recursive_term(i -1)+ fib_recursive_term(i -2)if n <0:raise Exception("n is negative")return[fib_recursive_term(i)for i inrange(n +1)]deffib_memoization(n:int)->list[int]: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]={0:0,1:1,2:1}# Prefilled cachedefrec_fn_memoized(num:int)->int: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(i)for i inrange(n +1)]deffib_binet(n:int)->list[int]:if n <0:raise Exception("n is negative")if n >=1475:raise Exception("n is too large")
sqrt_5 = sqrt(5)
phi =(1+ sqrt_5)/2return[round(phi**i / sqrt_5)for i inrange(n +1)]if __name__ =="__main__":
num =20
time_func(fib_iterative, num)
time_func(fib_recursive, num)
time_func(fib_memoization, num)
time_func(fib_binet, num)