; fizzbuzz
(define range
(case-lambda
((stop) (range 0 stop (if (negative? stop) -1 1)))
((start stop) (range start stop (if (< start stop) 1 -1)))
((start stop step)
(let ((le? (if (negative? step) >= <=)))
(let loop ((x start) (xs (list)))
(if (le? stop x) (reverse xs)
(loop (+ x step) (cons x xs))))))
(else (error 'range "too many arguments"))))
(define (fb1 n) ; straight forward method
(define (fb n)
(cond ((zero? (modulo n 15)) 'FizzBuzz)
((zero? (modulo n 5)) 'Buzz)
((zero? (modulo n 3)) 'Fizz)
(else n)))
(map fb (range 1 n)))
(display (fb1 26)) (newline)
(define (fb2 n) ; number theory method
(define (fb n)
(cdr (assoc (modulo (* n n n n) 15)
`((1 . ,n) (6 . Fizz) (10 . Buzz) (0 . FizzBuzz)))))
(map fb (range 1 n)))
(display (fb2 26)) (newline)
(define (fb3 n) ; sieving method
(let ((xs (list->vector (range n))))
(do ((i 3 (+ i 3))) ((<= n i))
(vector-set! xs i 'Fizz))
(do ((i 5 (+ i 5))) ((<= n i))
(vector-set! xs i 'Buzz))
(do ((i 15 (+ i 15))) ((<= n i))
(vector-set! xs i 'FizzBuzz))
(cdr (vector->list xs))))
(display (fb3 26)) (newline)
(define (fb4 n) ; simple euler method
(let loop ((i 1) (s 0))
(cond ((= n i) s)
((or (zero? (modulo i 3))
(zero? (modulo i 5)))
(loop (+ i 1) (+ s i)))
(else (loop (+ i 1) s)))))
(display (fb4 1000)) (newline)
(define (fb5 n) ; gauss summation method
(define (g n) (* n (+ n 1) 1/2))
(+ (* 3 (g (quotient (- n 1) 3)))
(* 5 (g (quotient (- n 1) 5)))
(* -15 (g (quotient (- n 1) 15)))))
(display (fb5 1000)) (newline)