[plt-scheme] Teaching Scheme

From: Stephen Bloch (sbloch at adelphi.edu)
Date: Mon May 3 12:08:46 EDT 2010

That again, more carefully thought-out, with comments, 

; door-open? : integer -> boolean
; Tells whether a given door is open at the end of the experiment.
; Since no pass larger than the door number can possibly affect it, we'll only run that many passes.
(define (door-open? door)
   (doh? door door))

; doh?, short for door-open-helper : integer integer -> boolean
; First parameter is the number of the door you're interested in.
; Second parameter is the number of the last pass you want to do.
(define (doh? door pass)
   (cond [(= pass 0) true]                                       ; on pass 0, make everything open
              [(= (remainder door (+ pass 1)) pass) ; if door number is 1 less than a multiple of (pass+1), ...
               (not (doh? door (- pass 1)))]                 ; ... flip it
              [else (doh? door (- pass 1))]))               ; otherwise don't

; print-doors : list-of-boolean -> output, 1 line per list element
(define (print-doors doors)
  (for ((door-num (in-range (length doors)))
          (open? doors))
       (printf "Door #~a is ~a.~n"
               (if open? "open." "closed."))))
; Note that I've replicated the bug in the C program that prints an extra period on each line.

; print-doors-up-to : integer -> output
(define (print-doors-up-to n)
  (print-doors (build-list n door-open?)))

; To print the status of the first 75 doors, type
(print-doors-up-to 75)
; Note that this is the only place that we've mentioned any number other than 0 or 1.
; If the problem were changed to be 300 doors and 300 passes, the C program would
; have to be changed in 4 places (or a symbolic constant would have to be introduced
; with #define ); we can simply call print-doors-up-to with a different argument.  Of course,
; one COULD write a C program to take in the number of doors as an argument, but
; depending on the compiler, one might need to use malloc and pointers to get an array
; whose size isn't known until run-time.

; The C code isn't particularly well-structured: I would move the printing code into a separate
; function, so I could compute at one time and print at another without recomputing.  I've
; done basically the same thing in Scheme:
(define 400-doors (build-list 400 door-open?))
(print-doors 400-doors)
(print-doors 400-doors)

Stephen Bloch
sbloch at adelphi.edu

Posted on the users mailing list.