もっともぬるいFizzBuzz
FizzBuzzというのは、「どうしてプログラマに・・・プログラムが書けないのか?*1」の記事に出てくる、プログラマ面接のテスト問題です。
1〜100の数字に対して、3で割り切れる数なら"Fizz"、5で割り切れる数なら"Buzz"、3と5の両方で割り切れる数なら"FizzBuzz"、どれにもあてはまらなければ単にその数字をプリントアウトするというもの。
これが書けないのは本当にプログラムを書いたことがないのだろう、という程度の問題なので、腕におぼえのある人は「いかに短いコードで書くか」を競う、コードゴルフのゲームに走るわけです。
しかし上のエントリにも書いたように、文法知識と発想力を駆使したコードは本物の呪文と化します(笑)
正攻法で書いたFizzBuzzのコードがあれば、コードゴルフの面白みが少しは伝わるでしょうか?
for i in 1..100 if i%3 == 0 print "Fizz" end if i%5 == 0 print "Buzz" end unless i%3 == 0 or i%5 == 0 print i end puts end
12行162バイト。たとえば1行目のfor i in 1..100を、(1..100).each とか、1.upto(100) とか書き換えるとちょっと短くなるわけです。
if文とunless文の連続はif ... elsif ... else と直したくなりますが、そうすると15の倍数でFizzBuzzが出ませんね。
この節を2行にまとめるのはわりと簡単です。
for i in 1..100 s = "#{'Fizz' if i%3 == 0}#{'Buzz' if i%5 == 0}" puts (s == "")? i : s end
埋め込み文字列と三項演算子でぐっと短くなりましたが、なにをやってるかはかなりわかりにくくなりました(笑)
もう一工夫するとこの節は1行にできます。
for i in 1..100 puts ( (s = "#{'Fizz' if i%3 == 0}#{'Buzz' if i%5 == 0}") == "")? i : s end
sを代入しながら空文字列判定しています。カッコが多くてわけわかりません。
がんばって全部1行にまとめてみました。
1.upto(100){|i|puts(((s="#{i%3==0&&:Fizz}#{i%5==0&&:Buzz}")=="")?i:s)}
動きそうですがダメです。Fizz(Buzz)にならない部分が全部Falseになってしまいます。
そろそろ眠いのでおしまい。これをやるにはRDEの方が便利かも。