Even more dynamic programming

Bills

Last time we discussed a dynamic programming algorithm to find, given a set of bill denominations, the smallest (in terms of number of bills) set of bills that add up to a target amount. Today we implemented the algorithm in Python.

Here’s our implementation (see the lecture capture for more details):

def minimum_bills(total: int, denominations: list):
    bills = [[]]
    i = 1
    while i <= total:
        bills_i = None
        for denomination in denominations:
            if denomination <= i:
                possible_bills = bills[i - denomination] + [denomination]
                if not bills_i:
                    bills_i = possible_bills
                elif len(possible_bills) < len(best_bills):
                    bills_i = possible_bills
        bills.append(best_bills)
        i = i + 1
    return bills[total]

Notice that the basic structure here is identical to our dynamic programming implementation of the Fibonacci numbers. We’re keeping our solutions to subproblems in a list (minimum_bills). We initialize the list with the solution to minimum_bills(0), which is the empty list of bills (there’s only one way to produce a total of $0). Then we loop over the numbers between 1 and total, solving the problem in each case (using our stored subproblem solutions) and storing the result, bills_i, in the list.

We can simplify this code a bit using Python’s list comprehensions and list functions. Here’s the simplified version:

def minimum_bills(total: int, denominations: list):
    bills = [[]]
    i = 1
    while i <= total:
        options = [bills[i - denomination] + [denomination]
                   for denomination in denominations
                   if denomination <= i]
        bills_i = min(options, key=len)
        bills.append(bills_i)
        i += 1
    return bills[total]

The basic structure of the code is the same–we have our solutions list and our while loop. The difference is the computation of bills_i. We first get a list of the possible lists of bills. We then get the option whose length is smallest using min with the key parameter. Again, see the lecture capture for details!