#!/usr/bin/python3 # -*- coding: utf-8 -*- """ Efficiency discusion using fibonacci sequence: f(n) = f(n - 2) + f(n - 1) = 1 if n == 0 or n == 1 """ # fibonacci using a loop def fib_loop(n: int) -> int: "Computes first n fib numbers, using loop" a, b = 0, 1 # the first and second Fibonacci numbers for i in range(n): a, b = b, a + b return a print(fib_loop(10)) # recursive Fibonacci (inefficient) def fib_rec(n: int) -> int: """Return Fibonacci of x, where x is a non-negative int""" if n < 2: return n # or 1 else: return fib_rec(n - 1) + fib_rec(n - 2) print(fib_rec(10)) # %% Tail recursion # %% tail recursive fibonacci (efficient) def fib_rec_tail(n: int, previous: int = 0, current: int = 1, i: int = 0) -> int: """ Computes first n fib numbers, using tail recursion Another way of defaulting values. This is both more sensible and more dangerous, since the user can break it. """ if i < n: return fib_rec_tail(n, current, previous + current, i + 1) else: return previous print(fib_rec_tail(10)) # %% tail recursive fibonacci (efficient) def fib_rec_tail_wrapped(n: int) -> int: """ Computes first n fib numbers, using tail recursion One way of defaulting values, which hides the values. """ def go(previous: int, current: int, i: int) -> int: if i < n: return go(current, previous + current, i + 1) else: return previous return go(0, 1, 0) print(fib_rec_tail_wrapped(10))