Loops and recursion

More fun with while loops and recursion

Factorial

The factorial function comes up frequently in probability and statistics (among other disciplines). The factorial of n (written n! is the product of the first n integers; for instance,

3! = 3 * 2 * 1 = 6

How would we implement factorial using loops? How about recursion?

def factorial_loop(n: int) -> int:
    total = 1
    while n > 1:
        total = total * n
        n = n - 1
    return total

def factorial_rec(n: int) -> int:
    if n <= 1:
        return 1
    return n * factorial_rec(n - 1)

A list-shaped dictionary

Imagine we have a list formatted like this:

lst = ["Rhode Island", "Providence", "Vermont", "Montpelier", ...]

Weird list–what’s going on? It looks like someone tried to make a dictionary but messed up. How would we solve this problem?

We ended up with two versions of the code: one using a while loop and one using recursion. See the lecture capture for details.

def list_to_dictionary(l: lst) -> dict:
    result = {}
    index = 0
    while index < len(l) - 1:
        result[l[index]] = l[index + 1]
        index = index + 1
    return result
def list_to_dictionary_from_index(l: lst, res: dict, index: int) -> dict:
    if index + 1 >= len(l):
        return res
    else:
        res[l[index]] = l[index + 1]
        list_to_dictionary_from_index(l, res, index)

def list_to_dictionary(l: lst) -> dict:
    return list_to_dictionary_from_index(l, {}, 0)

Mutation

Let’s go back to sorting for a moment. Instead of implementing our own sorting function, though, we’ll use the one built in to Python. For instance:

> l = ["doug", "alex", "brantley"]
> l.sort()
> l
["alex", "brantley", "doug"]

sort is a method we can call on a list that sorts that list. Notice that, just like our insertion_sort function, it doesn’t return anything but it modifies the list.

There’s another way to get a sorted version of a list:

> l = ["doug", "alex", "brantley"]
> sorted(l)
["alex", "brantley", "doug"]
> l
["doug", "alex", "brantley"]

What’s the difference? If we were to implement sorted, what would its header look like? It would take a list and return a list–and wouldn’t modify the list we passed in!

Functions like sorted allow us to write Python programs that are more similar to the Pyret programs we wrote in CSCI 0111. Rather than storing data in variables and then modifying the contents of those variables, we can avoid modifying existing variables and instead create new data. Other functions that work in this style are map and filter, which work just like their counterparts in Pyret:

> list(map(lambda s: "cool " + s, ["doug", "alex", "brantley"]))
["cool doug", "cool alex", "cool brantley"]
> list(filter(lambda s: not s.startswith("d"), ["doug", "alex", "brantley"]))
["alex", "brantley"]
> list(map(lambda s: "HTA " + s, filter(lambda s: not s.startswith("d"), ["doug", "alex", "brantley"])))
["HTA alex", "HTA brantley"]