The objective of this assignment is to practice writing recursive functions.

In the United States, making change is easy. For example, suppose that you are asked to give out 87 cents of change. You would naturally use 3 quarters, 1 dime and 2 pennies. This uses 6 coins. Any other combination of coins that add up to 87 cents uses more than 6 coins. For example, 2 quarters, 3 dimes, 1 nickel and 2 pennies sum up to 87 cents but uses 8 coins. The strategy you used is called the "greedy method" because you take as many quarters as possible without going over 87 cents, then as many dimes as possible, then nickels and pennies. This strategy is optimal because 5 and 10 (the values of a nickel and a dime) divide evenly into 25 (the value of a quarter).

In some monetary systems, the values of the coins are not evenly divisible. For example, the old British coin system includes coins with outlandish values. A "farthing" is worth 1/4 of a penny. Twenty shillings make a pound, but twenty-one shillings make a "guinea". There is a six-pence coin, a four-pence coin called a "groat" and even a penny-halfpenny coin worth 1.5 pence! Not to mention half-crowns, angels, laurels, florins, half-nobles etc. (Read about the history of British coins.)

Now suppose that you had a cash register with a good supply of pennies, groats (four-pence coins) and six-pence coins. How would you make change? The greedy method no longer gives the optimal solution. For example, to make change for 8p, you could use 1 six-pence and 2 pennies, but you can also use 2 four-pence coins. For this project you are asked to write a program that minimizes the number of coins used to make change. To do this, you will use recursion and a dynamic programming algorithm. The algorithm works as follows. In order to make change for n pence, you recursively figure out the number of coins needed to make change for (n-1) pence, for (n-4) pence and (n-6) pence. The solutions to the recursive problem will tell you whether you should use a penny, a groat or a six-pence.

For example, to make change for 56p, we recursively determine that the best ways to make change for 55p, 52p and 50p are the following,

55p: 9 six-pences, 1 penny

52p: 8 six-pences, 1 groat

50p: 7 six-pences, 2 groats

Thus, we can conclude that the best way to make change for 56p is to use 8 six-pences and 2 groats.

This assignment is broken into 3 levels. If you complete the basic level, you receive 85% of the project grade. If you complete the first two levels, you receive 95% of the project grade. If you complete all three levels, you receive 100% of the project grade.

For the basic level, your program must contain a recursive function that finds the optimum number of coins to make change using pennies, groats and six-pences. Specifically, you should have a recursive function with the following prototype:

The function `MakeChange()` must be a recursive function that
returns a structure representing the optimum way to make change for n
pence. For example, `MakeChange(56)` should return a
`change_t` structure where the Penny field is 0, the Groat field is
2 and the SixPence field is 8, because the optimum change for 56p uses 8
six-pences and 2 groats, as discussed above. If your project implements
`MakeChange()` correctly, you will receive 85% of the project grade.

It turns out that a call to `MakeChange()` will recursively call
`MakeChange(n)` for the same values of n many times. To speed up
your program, implement a memoization table for `MakeChange()`. The
memoization table will record for each value of n, whether
`MakeChange(n)` has already been computed. You should modify
`MakeChange()` so that when `MakeChange(n)` is called, it
first checks the memoization table to see whether `MakeChange(n)`
has been called previously. If so, it should simply return the value stored
in the table rather than continue with recursive calls. If no call to
`MakeChange(n)` has been made, then the function will proceed as
before, except that the return value for `MakeChange(n)` is stored
in the memoization table before returning. Note that the size of the
memoization table depends on the user's input. Thus, the memoization table
must be a dynamically allocated array. Implementing the memoization table
will decrease the running time of your program significantly and will give
you 95% of the project grade.

To receive 100% of the project grade, modify your program to query the user for the number and values of the coins in the user's cash register. Your program should allow the user to enter an arbitrary number of coins with arbitrary positive valuations for each coin. To do this, you must use a dynamically allocated array in place of the change_t type defined above. Your program must also use a memoization table.

As usual, please include the following statement in the comment section of your program:

I have read and I understand the course policy on cheating. By submitting the following program, I am stating that the program was produced by my individual effort.

Turn in your program using the UNIX submit utility. For this project, you may break up your program into several files, if you wish. Create a transcript of sample runs of your program using the script utility. You should choose examples that demonstrate the correctness and robustness of your program. Submit only your source code and the transcript -- do not submit any executable files.

This project is due by midnight (1 minute after 11:59pm) on Wednesday, February 25, 1998. We will use the system clock as the final arbiter of time and date. If you turn in your project on time, you will receive a 5% bonus on your project grade. There is a grace period of 2 days, but after midnight on Friday, February 27, no more projects will be accepted.

Last Modified: 23 Mar 1998 13:08:17 EST by Richard Chang

Back up to Spring 1998 CMSC 202 Section Homepage