def memo(f): """Return a function that behaves like f but caches return values. Note: This version accepts a function of any number of arguments. The simpler version in the slides accepts functions of only one argument. """ cache = {} def memoized(*args): if args not in cache: cache[args] = f(*args) return cache[args] return memoized def fib(n): """Return the nth Fibonacci number >>> fib(6) 5 """ if n == 1: return 0 if n == 2: return 1 return fib(n-2) + fib(n-1) def fib_iter(n): """Return the nth Fibonacci number >>> fib_iter(6) 5 """ prev, curr = 1, 0 for _ in range(n-1): prev, curr = curr, prev + curr return curr def count_change(a, kinds=(50, 25, 10, 5, 1)): """Return the number of ways to change amount a using coin kinds. >>> count_change(30) 18 """ if a == 0: return 1 if a < 0 or len(kinds) == 0: return 0 d = kinds[0] return count_change(a, kinds[1:]) + count_change(a - d, kinds)