Newsgroups: comp.lang.scheme
Path: cantaloupe.srv.cs.cmu.edu!rochester!udel!cnn.Princeton.EDU!princeton!siemens!scr.siemens.com!bap
From: Barak.Pearlmutter@scr.siemens.com (Barak Pearlmutter)
Subject: Re: Change-count from SICP as an ITERATIVE procedure?
In-Reply-To: aumuelle@mi.uni-erlangen.de's message of 18 Jan 1996 21:08:50 GMT
Message-ID: <BAP.96Jan20011702@scr.siemens.com>
Sender: news@scr.siemens.com (NeTnEwS)
Nntp-Posting-Host: gull.scr.siemens.com
Reply-To: barak.pearlmutter@alumni.cs.cmu.edu
Organization: Siemens Corporate Research
References: <4dmct2$hhd@rznews.rrze.uni-erlangen.de>
Date: Sat, 20 Jan 1996 06:17:02 GMT
Lines: 46

This is the way I compute the number of ways to make change.  It
entails only a small constant amount of stack growth regardless of the
argument, so I suppose that means it is iterative.

----------------------------------------------------------------

;;; Number of ways of giving change on c cents using pennies, nickels,
;;; dimes, and quarters:

;;; Case on (c mod 50) with each case determining the coefficients of
;;; a fourth order polynomial of floor(c/50).

(define (change c)
  (let* ((c5 (quotient c 5))
	 (q (quotient c5 10))
	 (r (modulo c5 10)))
    (+ (* (a r)        (choose (+ q 4) 4))
       (* (a (+ r 10)) (choose (+ q 3) 4))
       (* (a (+ r 20)) (choose (+ q 2) 4))
       (* (a (+ r 30)) (choose (+ q 1) 4)))))

;;; Coefficients of the polynomial a(z) = (1-z^{10})^5 / (1-z)^2
;;; (1-z^2) (1-z^5) (1-z^{10}).  The end should be zero padded to
;;; infinity, but the arguments given are always between 0 and 39
;;; inclusive.

(define (a i)
  (nth '(01 02 04 06 09 13 18 24 31 39 45 52 57 63 67 69
	    69 67 63 57 52 45 39 31 24 18 13 09 06 04 02 01
	    0 0 0 0 0 0 0 0)
       i))

;;; This computes the number of subsets of size m of a set of size n.
;;; The arguments are in the usual order, "n choose m."

(define (choose n m)
  (let aux ((n n)(m1 m)(total 1))
    (if (= m1 0)
	(let aux ((m m)(total2 1))
	  (if (= m 0)
	      (/ total total2)
	      (aux (- m 1) (* m total2))))
	(aux (- n 1) (- m1 1) (* n total)))))

;;; Test case, the number of ways of giving change for $1,000,000.00
;;; (change 100000000) = 66666793333412666685000001.
