私自身が表題の問題を解いた時のプログラムについて解説します。
問題の詳細は「FizzBuzz?やつは四天王の中でも最弱-CodeIQ四天王」(CodeIQ)を参照してください。
Pythonで解答しています。
#!/usr/local/bin/python3
# -*- coding:utf-8 -*-
import fileinput
import sys
# HelloWorldを引数の回数繰り返し出力
def doHelloWorld(v):
sys.stdout.write("HelloWorld" * v)
# 入力値を判断してFizzBuzzを出力
def doFizzBuzz(v):
if v%15 == 0:
sys.stdout.write("FizzBuzz")
elif v%5 == 0:
sys.stdout.write("Buzz")
elif v%3 == 0:
sys.stdout.write("Fizz")
else:
sys.stdout.write(str(v))
# 引数番目の素数を出力。15個しかないので表を使う
def doPrime(v):
p = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]
sys.stdout.write(str(p[v-1]))
# 引数番目のフィボナッチ数を出力。15個しかないので表を使う
def doFibonacci(v):
f = [1,1,2,3,5,8,13,21,34,55,89,144,233,377,610]
sys.stdout.write(str(f[v-1]))
Funcs = {
"HelloWorld":doHelloWorld,
"FizzBuzz":doFizzBuzz,
"Prime":doPrime,
"Fibonacci":doFibonacci,
}
if __name__ == "__main__":
for line in fileinput.input():
if not line.strip():
continue
cmd, val = line.strip().split(",")
Funcs[cmd](int(val))
どうこう言うような問題ではありませんが、ちょっとして工夫があります。
素数とフィボナッチ数列ですが仕様で15個しかないことが明らかです。
たかだか15個しかないものを計算すするのは無駄ですので表引きにしてしまいました。O(1)の計算量で済みます。確かK&Rの『プログラミング言語C」にも書いてあったと思うのですが、はっきりとわかっている結果はああらかじめ計算しておいてそれを使うというのは有効な手段です。
32〜37行目のディクショナリです。キーに対してそれを処理する関数をセットしています。実際の呼び出しは46行目ですがディクリョナリで得た値を関数として解決しています。
このようなファンクションテーブルは入力によって処理を動的に決定したい場合に使える有効なテクニックです。プログラムの見通しも良くなりますし、機能追加や削除も容易です。条件文による処理よりもずっと優れています。
この文章を書きながら思ったのですが、この問題の趣旨はどれだけ華麗なプログラムを書けるのかにあるのかもしれません。4つの関数を全て結果の文字列を返すようにすればラムダ式で書けるので32〜37行目のvalueに直接設定すれば7〜30行目までがなくなってすごく短くなります。
こんな感じ。
#!/usr/local/bin/python3
import fileinput
import sys
Funcs = {
"HelloWorld": (lambda n: "HelloWorld" * n),
"FizzBuzz": (lambda n: "FizzBuzz" if n%15 == 0 else ( "Buzz" if n%5 == 0 else ( "Fizz" if n%3 == 0 else str(n)))),
"Prime": (lambda n: str([2,3,5,7,11,13,17,19,23,29,31,37,41,43,47][n])),
"Fibonacchi": (lambda n: str([1,1,2,3,5,8,13,21,34,55,89,144,233,377,610][n])),
}
if __name__ == "__main__":
for line in fileinput.input():
if not line.strip():
continue
cmd, val = line.strip().split(",")
sys.stdout.write(Funcs[cmd](int(val)))