プログラミングを頑張る日記

プログラミングを勉強して、ハッカーになろう

Common Lispを頑張る(8)

今日は趣向を変えてLispfizzbuzzでも書こうと思います。
残業して家帰ってきたら23時回っており、勉強する体力が無いからです…。

とりあえず思いついたやつがこちらです。

CL-USER> (defun fizzbuzz (n max)
	     (if (< n max)
		 (cond ((= 0 (mod n 15))
			(princ "fizzbuzz"))
		       ((= 0 (mod n 3))
			(princ "fizz"))
		       ((= 0 (mod n 5))
			(princ "buzz"))
		       (t (princ n))))
	     (setq n (+ n 1))
	     (fizzbuzz n max))
FIZZBUZZ
CL-USER>

ローカル変数でnの値を定義して、それで次のfizzbuzzにどうやって渡すか
悩んだりしましたが、諦めて引数でもらうことにしました。
グローバル関数を定義するのはなんか嫌でこうしたのですが、五十歩百歩な感じです。
処理自体にコメントすることはないです。
もっといい感じに書く方法が思いつかないです…。
グチグチ言ってると悲しくなってきたので、実際に動かしてみます。

CL-USER> (fizzbuzz 1 30)
12fizz4buzzfizz78fizzbuzz11fizz1314fizzbuzz1617fizz19buzzfizz2223fizzbuzz26fizz2829

; No value; Evaluation aborted on NIL.

CL-USER>

無限ループに入ってしまったのでC-c C-cで処理を中断しました。
これは、ifがcondのところにしかかかってないので、
ずっとnを増やしながらfizzbuzzを呼んじゃってたんですね。情けない。

あと、改行が必要ですね。
princならなんとかしてくれるんじゃないかと思ってましたが間違いだったようです。

それと…29で処理が途切れていますね。これはひどい
普通(fizzbuzz 1 30)と呼び出したら1から30のfizzbuzzをしてくれると
思うはずなので、判定の部分を修正せねばなりません。
「ああ、疲れてるんだな、可哀想な人…」ぐらいで見逃してください。

それでは修正します。

CL-USER> (defun fizzbuzz (n max)
	     (when (< n (+ max 1))
		 (cond ((= 0 (mod n 15))
			(princ "fizzbuzz"))
		       ((= 0 (mod n 3))
			(princ "fizz"))
		       ((= 0 (mod n 5))
			(princ "buzz"))
		       (t (princ n)))
		 (princ #\newline)
		 (setq n (+ n 1))
		 (fizzbuzz n max)))
WARNING: redefining COMMON-LISP-USER::FIZZBUZZ in DEFUN
FIZZBUZZ
CL-USER> (fizzbuzz 1 30)
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
16
17
fizz
19
buzz
fizz
22
23
fizz
buzz
26
fizz
28
29
fizzbuzz
NIL
CL-USER>

ふう、できたようです。

完成形をみたら、世界に向けて公開するのが恥ずかしくなってきました。
でも公開します。
いつか「昔はこんなの書いてたね〜」と笑えるようになると信じて…!

あ、今気づけた、これsetq要らないですね。
1増やしたの渡せばいいだけだった。
…おやすみなさい。