The cashier problem is specified as follows. The function solving the problem has two arguments:
As the function's return value, we expect:
Note that as a precondition it is assumed that the list passed as the function's second argument is already sorted.
A greedy algorithm for this problem starts with an empty list (of coins). It keeps appending that list by the largest possible coin, without ever exceeding the requested amount. Eventually, the requested amount is reached, and the finalized list is returned. In the greedy cashier notebook, this is implemented as follows:
def cashier(amount, coin_types): coins = [] remainder = amount while remainder >= coin_types[0]: for i in range(len(coin_types)-1, -1, -1): if remainder >= coin_types[i]: coins.append(coin_types[i]) remainder -= coin_types[i] break return coins
Above, the expression range(len(coin_types)-1, -1, -1) is used to traverse the list in reverse order, beginning with the greatest coin type.
In the notebook, this is applied to two coin systems, the conventional one, [1, 2, 5, 10, 20, 50, 100, 200], and an alternative one, [1, 8, 27, 64, 125, 216, 343, 512]. For an amount given as 93, the greedy algorithm returns [50, 20, 20, 2, 1] for standard coins and [64, 27, 1, 1] for the alternative coins.
Discussion: We know from experience that the algorithm above works correctly for the conventional coin system, i.e., it returns the shortest possible list of coin values adding up to any integer number. Does it work correctly for the alternative coin system? If it does not, what would be a counterexample?
To avoid the case where an integer value cannot be produced by a coin system at all, it can be assumed that the value 1 is always included among the existing coin types.
Submission deadline: 27th November 2021; discussion planned for 9th December 2021. Group work by up to four people is welcome.