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!