(define tower-of-hanoi
  (lambda (n)
    (letrec
     ((move
       (lambda (n source destination helper)
	 (if (= n 1)
	     (list (list source destination))
	     (append
	      (move (sub1 n) source helper destination)
	      (cons
	       (list source destination)
	       (move (sub1 n) helper destination source)))
	     ))))

     (move n 'L 'R 'C))))

(define animate-hanoi
  (lambda (n)
    (letrec
     ((init-needle
       (lambda (n i)
	 (if (= n 0)
	     ()
	     (cons i (init-needle (sub1 n) (add1 i))))))
      (L (init-needle n 0))
      (C ())
      (R ())
      (display-needles
       (lambda (L C R)
	 (newline)
	 (display "L ")
	 (display (reverse L))
	 (newline)
	 (display "C ")
	 (display (reverse C))
	 (newline)
	 (display "R ")
	 (display (reverse R))
	 (newline)))
      (loop
       (lambda (moves L C R)
	 (display-needles L C R)
	 (cond ((null? moves)
		(display "Done!")
		(newline))
	       (else
		(letrec
		 ((source (caar moves))
		  (destination (cadar moves))
		  (disk
		   (cond ((eq? source 'L) (car L))
			 ((eq? source 'C) (car C))
			 (else
			  (car R))))
		  (update-needle
		   (lambda (needle contents)
		     (cond ((eq? needle source)
			    (cdr contents))
			   ((eq? needle destination)
			    (cons disk contents))
			   (else
			    (contents))))))
		 (newline)
		 (display source)
		 (display "->")
		 (display destination)
		 (loop (cdr moves)
		       (update-needle 'L L)
		       (update-needle 'C C)
		       (update-needle 'R R))))))))

     (loop (tower-of-hanoi n) L C R))))