Finally, I’ve finished a pure math project and two computational humanities projects, and I have some free time on my hand. So, I thought it is time that I wrote my own version of fizz-buzz in Common Lisp.
One can find many different solutions for the problem at Rosetta Code. The solution I have is slightly different. I always hated the straightforward solution that checks divisibility by 15 first then by 5 then by 3 because the last two precludes the first. Anyway, here is yet another solution for fizz-buzz:
First, I need a function that does function composition:
(defun compose (&rest fs)
(lambda (x)
(let ((res x))
(dolist (f (reverse fs) res)
(setf res (funcall f res))))))
COMPOSE
Next, I need functions that do the right thing for a given number:
(defun do-the-right-thing (k response)
(lambda (x)
(if (atom x)
(if (zerop (mod x k)) (cons x response) x)
(if (zerop (mod (car x) k)) (cons (car x) (cons response (cdr x))) x))))
DO-THE-RIGHT-THING
And the final code:
(let ((fizz (do-the-right-thing 3 :fizz))
(buzz (do-the-right-thing 5 :buzz))
(extract (lambda (x) (if (atom x) x (cdr x)))))
(mapcar (compose extract fizz buzz) (loop for i from 0 to 50 collect i)))
((FIZZ . BUZZ) 1 2 FIZZ 4 BUZZ FIZZ 7 8 FIZZ BUZZ 11 FIZZ 13 14 (FIZZ . BUZZ)
16 17 FIZZ 19 BUZZ FIZZ 22 23 FIZZ BUZZ 26 FIZZ 28 29 (FIZZ . BUZZ) 31 32 FIZZ
34 BUZZ FIZZ 37 38 FIZZ BUZZ 41 FIZZ 43 44 (FIZZ . BUZZ) 46 47 FIZZ 49 BUZZ)