commonlispでFizzbuzz問題を解いてみる
最初の実装
まずはシンプルなFizzBuzz実装から始める。1から100までの数字を列挙し以下の条件に基づいて出力する。
- 3で割り切れる場合は "Fizz"
- 5で割り切れる場合は "Buzz"
(dotimes (i 100) (let* ((n (1+ i)) (fizz (if (zerop (mod n 3)) "Fizz" "")) (buzz (if (zerop (mod n 5)) "Buzz" "")) (fizzbuzz (concatenate 'string fizz buzz))) (format t "~a~%" (if (string= fizzbuzz "") n fizzbuzz))))
これでFizzBuzzの基本的な実装が完成した。ここからコードを拡張する。
拡張版実装
こちらではルールを柔軟に追加できるようにした。
(defun print_fizzbuzz (i rules) (let* ((n (1+ i)) (result (reduce (lambda (acc rule) (let ((condition (first rule)) (output (second rule))) (if (funcall condition n) (concatenate 'string acc output) acc))) rules :initial-value ""))) (if (string= result "") n result))) (defun print_fizzbuzz_with_rules (limit rules) (dotimes (i limit) (let ((result (print_fizzbuzz i rules))) (format t "~a~%" result)))) (let ((rules (list (list #'(lambda (n) (zerop (mod n 3))) "Fizz") (list #'(lambda (n) (zerop (mod n 5))) "Buzz")))) (print_fizzbuzz_with_rules 100 rules))
拡張版では rules 変数にルールを追加することで、例えば「7で割り切れる時は "hoge" を返す」といった機能を簡単に追加できるようになった。 また表示とルールを分離することでテストしやすいコードになった。