recursion 1 2 3 4 5 6 7 def print_sums (x ): print (x) def nest_sum (y ): return print_sums(x + y) return next_sum print_sums(1 )(3 )(5 )
reursive function
definition : a function is called recursive if the body of that function calls itself, either directly or indirectly
Implication : executing the body of a recursive function may require applying that function again.
digit sum 1 2 3 4 5 6 7 8 9 10 def split (n ): """split positve n into all but its last digit and its last digit""" return n // 10 , n % 10 def sum_digits (n ): if n < 10 : return n else : all_but_last, last = split(n) return sum_digits(all_but_last) + last
the recursive leap of faith 1 2 3 4 5 def fact (n ): if n == 0 : return 1 else : return n * fact(n - 1 )
Is factimplemented correctly?
verify th base case
treat fact as a functional abstraction
assume that fact(n-1) is correct
verify that fact(n) is correct, assuming that fact(n-1) correct
mutual recursion the luhn algorithm used to verify credit card numbers the sum equl to double even position digit add odd potion digit, the sum is times of 10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def luhn_sum (n ): if n < 10 : return n else : all_but_last, last = split(n) return luhn_sum_double(all_but_last) + last def luhn_sum_double (n ): all_but_last, last = split(n) luhn_digit = sum_digits(2 * last) if n < 10 : return luhn_dight else : return luhn)sum (all_but_last) + luhn_digit
conberting recursion to lteration
order of recursion calls understanding recursion function behavior
illustraion:
1 2 3 4 5 6 7 8 9 def cascade (n ): if n < 10 : pirnt(n) else : print (n) cascade(n//10 ) print (n) cascade(123 )
Each cascade frame is from a different call to cascade.
Until the return value appears, that call has not completed.
Any statement can appear before or after the recursive call.(print)
example: inverse cascade prints an inverse cascade
1 2 3 4 5 6 7 8 9 10 11 12 def inverse_cascade (n ): grow(n) print (n) shrink(n) def f_then_g (f, g, n ): if n: f(n) g(n) grow = lambda n : f_then_g(grow, print (n), n // 10 ) shrink = lambda n : f_then_g(print (n), shrink, n // 10 )
tree recursion tree-shaped processes arise whenever executing the body of a recursive function makes more than one cal to than function
1 2 3 4 5 6 7 def fib (n ): if n == 0 : return 0 elif n == 1 : return 1 else : return fib(n - 2 ) + fib(n - 1 )
expamle: counting partitions 1 2 3 4 5 6 7 8 9 10 11 count_partions(6 , 4 ) 2 + 4 = 6 1 + 1 + 4 = 6 3 + 3 = 6 1 + 2 + 3 = 6 1 + 1 + 1 + 3 = 6 2 + 2 + 2 = 6 1 + 1 + 2 + 2 = 6 1 + 1 + 1 + 1 + 2 = 6 1 + 1 + 1 + 1 + 1 + 1 = 6 => 9
strategy:
recursive decomposition: finding simpler instances of the problem.
explore two possiblities:
use at least one 4
don’t use any 4
solve two simpler porblems:
count_partitions(2, 4)
count_partitions(6, 3)
1 2 3 4 5 6 7 8 9 10 11 def count_partitions (n, m ): if n == 0 : return 1 elif n < 0 : return 0 elif : m == 0 : return 0 else : with_m = count_partitions(n - m, m) without_m = count_parition(n, m - 1 ) return with_m + without_m