Example: Counting Change

In this Example, we write a recursive procedure to calculate the number of possible ways to tend change to a given value.

The Problem

Suppose you have a sum of 1 dollar. Let’s say you bought a coffee for 90 cents, and the cafeteria needs to pay you back 10 cents. How do find number of ways to the cafeteria can pay you back your change? One such way is to manually count the possible ways.

$$ 10 = 10 $$
$$ 5 + 5 = 10 $$
$$ 5 + 1 + 1 + 1 + 1 + 1 = 10 $$
$$ 1 \times 10 = 10 $$

If this was a larger number, it would just go on and on. Ugh. So how do you count the change for a number like $0.25 let alone any given number?

My thoughts

When you ask for change, say from a shop, you always ask for the biggest denomination. In the case of the cafeteria, you would probably expect a dime as change. If a dime is missing, you ask for the next largest denomination i.e a nickel. Now the Cafe owes you 10 - 5 dollars i.e 5 dollars. If there’s still another nickel, you would take it. But if they don’t have a nickel, you would have to take 5 pennies. But what if they have only pennies? you would have to take 10 pennies then!

So in short the number of ways to tend 0.10 dollars is the sum of the ways we can tend change to 0.05 dollars and the ways we only used pennies

Making a better description

The real-life description above gives a very vague description about how we calculate the ways to tend change. Let us build on it to make a function for counting change.

Essentially what we are doing is taking an amount ($0.10) and breaking it down by subtracting from the amount the value of a denomination. We then find the number of ways we can tend change to that new amount, and then add that to number of ways we can tend change to amount - another denomination.

Managing Denominations

But how do count ways that sucessful and not count the way that aren’t? For that we must figure out how to manage the usable denominations. We make a function that will return the nth denomination. So this would can be easily defined as:

(define (first-denomination k)
  (cond ((= k 1) 1)
        ((= k 2) 5)
        ((= k 3) 10)
        ((= k 4) 25)
        ((= k 5) 50)))

Now to make our program compatible with another currency, all you will have to do is adjust this function accordingly.

Counting change

We now have description that is still quite vague but gives us an idea of what is happening. Let us improve it even more.

We said that essentially we are adding the sum of ways(amount - first-denomination(n)) where we add the value of all ways (with n having different values). Let us change this bit. We will add the concept of being allowed use a certain type of coin and all coins below that. We will also change our logic a bit:

ways{ 100, 5 } = ways{ 100, 5 - 1 }      ;   never use any 50-cent coins
                 +                       ; OR
                 ways{ 100 - 50,  5 }    ;   may use 50-cent coins, so use one

We will sum the ways we can use 50 cents and subtract from amount 50, or not never use 50 cent coins so that we can find another not involving 50 cents. (In this case, this can be 25 + 25 + 25 + 25)

In general we sum ways(amount - first-denomination(k), k) and ways(amount, k - 1).

Now we can define what happens when we have reached, the end of the algorithm: when on the params are 0 or less than 0:

Writing the code

We shall now define our recursive procedure:

(define (cc amount kind-of-coins)
  (cond ((= amount 0)1)
        ((or (< amount 0)  (= kinds-of-coins 0)) 0)
        (else (+ (cc amount
                     (- kinds-of-coins 1))
                 (cc (- amount
                        (first-denomination kinds-of-coins))
                    kinds-of-coins)))))

This entire script is:

(define (count-change amount)
  (cc 5 amount))

(define (cc n-value amount)
  (cond ((= amount 0 ) 1)
	(( or (= n-value 0) (< amount n-value)) 0)
	(else (+ (cc (- n-value 1 ) amount) 
		 (cc n-value (- amount (first-denomination n-value)))))))

(define (first-denomination n)
  (cond ((= n 1) 1)
  ((= n 2) 5)
  ((= n 3) 10)
  ((= n 4) 25)
  ((= n 5) 50)))

This when used with 1 dollar, will give 292.