Question

I am just exploring functional programming via SICP, and am wondering how I can extend Exercise 2.19 to do something more useful (and which seems to require side-effects).

The exercise involves a program that counts the number of ways one can make change for a given amount (in pennies) with a given a list of coin denominations. The solutions is quite simple (cc stands for "count-change"):

(define (cc amount coin-values)
  (cond ((= amount 0) 1)
        ((or (< amount 0) (no-more? coin-values)) 0)
        (else
         (+ (cc amount
                (except-first-denomination coin-values))
            (cc (- amount
                   (first-denomination coin-values))
                coin-values)))))

(define (first-denomination coinTypes) (car coinTypes))
(define (except-first-denomination coinTypes) (cdr coinTypes))
(define (no-more? coinTypes) (null? coinTypes))

You can see the relevant SICP section here and this links to description of the algorithm if above is not clear.

I first wanted to see what actual combinations of coins constitute each way to make change so I wrote my own version that prints out each solution as a list:

(define (count-change amount coinTypes)
    (define (cc amount coinTypes currChangeList)
        (cond ((= amount 0) 
                    (display (reverse currChangeList)) 
                    (newline) 
                    1)
              ((or (negative? amount) (null? coinTypes)) 
                    0)
              (else (+ (cc amount (cdr coinTypes) currChangeList)
                       (cc (- amount (car coinTypes)) coinTypes (cons (car coinTypes) currChangeList))))))
    (cc amount coinTypes ()))

So here's where I am stuck: I want to modify my method so that instead of returning an integer result = # of ways to make change, and simply printing each way during it's computation, I want it to return a list of the solutions (a list of lists, the length of which = # of ways to make change). However, I am at a loss of how to make this happen. It's easy to do in imperative/OO languages, but I can't figure out how to do it functionally.

Does anybody have any idea of how to achieve this? It seems like it should be a pretty easy thing to do for an experienced functional coder.. Please help satisfy my curiosity, and net yourself some coding karma :)

Thanks

Was it helpful?

Solution

(define (count-change amount coinTypes)
    (define (cc amount coinTypes currChangeList)
        (cond ((= amount 0) 
               (list (reverse currChangeList)))
              ((or (negative? amount) (null? coinTypes)) 
               '())
              (else
                (append
                   (cc amount (cdr coinTypes) currChangeList)
                   (cc (- amount (car coinTypes))
                       coinTypes
                       (cons (car coinTypes) currChangeList))))))
    (cc amount coinTypes '()))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top