Recursion - Wed, Sep 18

Recursive Functions

A function is recursive if the body of that function calls itself, directly or indirectly.

Digit Sums

This is useful for typo correction, such as on credit cards. The last digit is the checksum digit.

The Problem Within the Problem

This is recursion.

def split(n):
    """Split positive n into all but its last digit and its last digit."""
    return n // 10, n % 10

def sum_digits(n):
    """Return the sum of the digits of positive integer n."""
    if n < 10:
        return n
    else:
        all_but_last, last = split(n)
        return sum_digits(all_but_last) + last

Iteration vs. Recursion

Iteration is a special case of recursion:

def fact_iter(n):
    total, k = 1, 1
    while k <= n:
        total, k = total*k, k+1
    return total

The above function is equivalent to the recursive function we wrote before. However, the iterative function runs faster in Python than the recursive function because creating new frames takes a little bit of time. However, other languages process code differently and more efficiently, doing the same thing under the hood for both functions, so the run speed is similar/the same.

The iterative function uses four names: n, total, k, fact_iter. The recursive function does the same thing with just two names: n, fact.

Verifying Recursion Using the Recursive Leap of Faith

def fact(n):
    if n == 0:
        return 1
    else:
        return n * fact(n-1)

Is fact implemented correctly? 1. Verify the base case 2. Treat fact as a functional abstraction 3. Assume that fact(n-1) is correct 4. Verify that fact(n) is correct

Essentially, assume that fact works for simpler instances of the same problem. If it does, you can generalize your conclusion to all uses of fact.

Mutual Recursion Using the Luhn Algorithm

A function f calls a function g which calls f which calls g and so on and so forth.

The Luhn Algorithm is used to verify credit card numbers. From Wikipedia:

First: From the rightmost digit, which is the check digit, moving left, double the value of every second digit; if product of this doubling operation is greater than 9 (e.g., 7 * 2 = 14), then sum the digits of the products (e.g., 10: 1 + 0 = 1, 14: 1 + 4 = 5)

Second: Take the sum of all the digits

The Luhn sum of a valid credit card number is a multiple of 10.

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_digit
    else:
        return luhn_sum(all_but_last) + luhn_digit

Converting Iteration to Recursion

Formulaic: Iteration is a special case of recursion. Idea: The state of an iteration can be passed as arguments.