Students will be able to (1) employ the methodology of top-down dynamic programming using recursion and memoization, (2) employ the methodology of bottom-up dynamic programming, and (3) explain the kinds of savings in compute-time offered by the methodology of dynamic programming.
Read this article on Dynamic Programming and this article on Dynamic Programming and browse the section on Dynamic Programming on Geeks for Geeks.
You’ve found yourself in a post-apocalyptic world with no Apple Pay, no Bitcoin, and no credit cards. No paper money either. People use... big, heavy, coins. Coins are heavy so one of the more important reasons for computation in this society is to minimize the number of coins that comprise a given amount. Each region in this world has its own set of monetary units. One region has units of 1, 29, and 493 (sounds like 🧙right?). Another has 1, 4, 5, and 7. Another has 1, 11, 13, 29, and 31. Can you figure out the minimum number of coins for a given amount for any set of coin denominations?
As in the previous labs, go to GitHub, select Import Repository. Then:
The import might take a few minutes. When done, clone the repo and get ready to work.
The starter code has two classes:
CoinChanger.TopDown
CoinChanger.BottomUp
Each has a minCoins
method for you to complete. minCoins(
$a$, $\{d_1...d_n\}$)
is to return the minimum number of coins, total, to make the amount $a$ given the set of coin denominations $\{d_1...d_n\}$. For example:
minCoins(8, {1, 4, 5}) ⇒ 2 // two 4-cent coins minCoins(600, {1, 29, 493}) ⇒ 24 // one 493-cent coin, // three 29-cent coin, // twenty 1-cent coins
If minCoins
is called without a 1-unit denomination, throw an error. If any one of the denominations are zero or negative, throw an error.
Now here’s the thing. Coin changing, if done “brute-force”, that is, by trying all possibilities, can take forever. In this lab, you are going to practice Dynamic Programming, a way of solving optimization problems more quickly than by trying all possibilities. During lecture, we will learn how dynamic programming can proceed top-down or bottom-up. You will implement both approaches, and study which one is better under which conditions. This is, after all, a laboratory assignment!
Based on your understanding of top-down and bottom-up dynamic programming, determine in what kinds of scenarios the top-down approach should be faster and in which scenarios bottom-up should be faster. Write up your thoughts, but also run timing studies on the methods you wrote. What kinds of scenarios should you consider? It’s up to you, but you might want to think about large vs. small amounts (relative to the denominations), wide vs. small gaps between denominations, large vs. small sets of denominations, and so on.
In this lab, you do not need any main
methods. For your experiments, use JShell!
A single unit test suite combining tests for both of your methods is provided in the starter code. Use it as follows:
$ javac CoinTest.java && java CoinTest
This lab only requires you to compute the minimum number of coins that make up a certain amount. You may wish to try to add additional methods that tell you how many of each type of coin are present in this minimal coin set. For example:
minimalCoinSet(8, {1, 4, 5}) ⇒ {4: 2} // two 4-cent coins minimalCoinSet(600, {1, 29, 493}) ⇒ {493: 1, 29: 3, 1: 20} // one 493-cent coin, // three 29-cent coin, // twenty 1-cent coins
Begin working on the challenge after finishing up the assigned work. There will be no extra credit awarded for this challenge; complete it for your own personal satisfaction, if you have the time and energy.
Online:
On hardcopy or email:
HashMap
or a TreeMap
(or some other kind of map)? Why did you make that choice?