FizzBuzz

最強の FizzBuzz 拡張

FizzBuzz をどのように一般化、拡張化するのかを考察した。特に参考文献はないので新規性もないかもしれないし、間違っているかもしれない。

Step01. Fizz, Buzz, Inzz

3 で割り切れれば Fizz, 5 で割り切れれば Buzz, 7 でわりきれれば Inzz のように一つルールを増やすのが拡張の第一歩だろう。なお、Inzz という言葉を選んだのは、頭文字を並べると FBI になるから。

Step02. N個の変更ルール

Fizz, Buzz, Inzz だけでなく、これを可変個にするのは合理的な拡張になるだろう。「 3 で割り切れると Fizz を出す」というのは「 num で割り切れると value を出す関数」を返す関数 mutate の返り値だとみなせる。つまり、 fizz = mutate('fizz',3) だし、buzz = mutate('buzz',5) である。このように考えると、任意の個数の変更ルールに対する FizzBuzz というのは簡単に考える事ができよう。以下は 5つの変更ルールを擬似コードで示す。

rules = [
  mutate('Fizz', 3),
  mutate('Buzz', 5),
  mutate('Inzz', 7),
  mutate('Fuzz', 11),
  mutate('Unzz', 13),
]

Step03. 無限個の変更ルール

前Stepで任意の個数の変更ルールの下での FizzBuzz を考えたが、変更ルール自体は人間が定義する必要があった。もし変更ルールをアルゴリズムで生成できれば、無限個の変更ルールを持つFizzBuzzができるだろう。

変更ルールのアルゴリズム生成は容易だ。前Stepの最後の例を見ながら読んでほしい。 i 番目のルールとは、「i 番目の素数で割り切れる場合は、word(i) とう文字列を出す」、となる。なお、0 番目の素数は 2, 1 番目の素数は 3 である。word(i) を機械的に作りたければ Fi とでもすればよいだろう。

以上をまとめると、生成ロジックは以下のようになる。無限個の変更ルールを持つFizzBuzz の仕様ができた。

rules = [
  mutate('F1', prime(1)),
  mutate('F2', prime(2)),
  mutate('F3', prime(3)),
  mutate('F4', prime(4)),
  mutate('F5', prime(5)),
  ...
]

まとめ

FizzBuzz拡張ルール:

与えられた N に対して以下の処理を行え

  • 変更ルールi : N が i番目の素数で割り切れる場合は F${i} を出す
    • 0番目の素数は 2 とする
    • F${i} とは、例えば i=3のときは F3 を表す
  • Nに対して、上記変更ルールを全ての自然数 i に対して、i が小さい順に適用する。
  • 上記の結果なにも出力されなければ、N自身を出力する。

実行例。最初のいくつかの自然数に対しての結果を例示する。

1, 2, F1, 4, F2,
F1, F3, 8, F1, F2,
F4, F1, F5, F3, F1F2,
16, F6, ...

さらなる拡張

FizzBuzz が作用するのはただの自然数であるが、二次元、三次元上の点に拡張することも可能かな。