Problem 4: Count change (200pts)

Denomination is a proper description of a currency amount, usually for coins or banknotes. For example, we have 1 Yuan coins and 100 Yuan bills in Chinese Yuan.

A money function is a function which takes a positive integer representing a denomination and returns the next larger denomination of the input or None if there is no larger denomination. Its behavior is undefined if the input is not a valid denomination.

Money function can be used to describe a currency system. For example, the following money function describes Chinese Yuan (1 Yuan, 5 Yuan, 10 Yuan, 20 Yuan, 50 Yuan and 100 Yuan). You can assume the smallest denomination of all currencies is always 1.

def chinese_yuan(money): if money == 1: return 5 if money == 5: return 10 if money == 10: return 20 if money == 20: return 50 if money == 50: return 100

Given an amount of money total and a currency system, a set of banknotes (coins) makes change for total if sum of their values is exactly total. For example, the following sets make change for 15 Chinese Yuan:

  • 15 1-Yuan
  • 10 1-Yuan, 1 5-Yuan
  • 5 1-Yuan, 2 5-Yuan
  • 5 1-Yuan, 1 10-Yuan
  • 3 5-Yuan
  • 1 5-Yuan, 1 10-Yuan

Thus, there are 6 different ways to make change for 15 Chinese Yuan.

Write a recursive function count_change that takes a positive integer total and a money function next_money and returns the number of ways to make change for total under the currency system described by next_money.

Hint: Refer the implementation of count_partitions for an example of how to count the ways to sum up to a total with smaller parts. If you need to keep track of more than one value across recursive calls, consider writing a helper function.

def count_change(total, next_money): """Return the number of ways to make change for total, under the currency system described by next_money. >>> def chinese_yuan(money): ... if money == 1: ... return 5 ... if money == 5: ... return 10 ... if money == 10: ... return 20 ... if money == 20: ... return 50 ... if money == 50: ... return 100 >>> def us_cent(money): ... if money == 1: ... return 5 ... elif money == 5: ... return 10 ... elif money == 10: ... return 25 >>> count_change(15, chinese_yuan) 6 >>> count_change(49, chinese_yuan) 44 >>> count_change(49, us_cent) 39 >>> count_change(49, lambda x: x * 2) 692 >>> from construct_check import check >>> # ban iteration >>> check(HW_SOURCE_FILE, 'count_change', ['While', 'For']) True """ "*** YOUR CODE HERE ***"