アート・オブ・FizzBuzz

この記事はklis Advent Calendar 2016 - Adventar5日目の記事です。4日目の記事はこちら

みなさん、FizzBuzz書いてますか?

プレイヤーは円状に座る。最初のプレイヤーは「1」と数字を発言する。次のプレイヤーは直前のプレイヤーの次の数字を発言していく。ただし、3で割り切れる場合は「Fizz」(Bizz Buzzの場合は「Bizz」)、5で割り切れる場合は「Buzz」、両者で割り切れる場合(すなわち15で割り切れる場合)は「Fizz Buzz」(Bizz Buzzの場合は「Bizz Buzz」)を数の代わりに発言しなければならない。発言を間違えた者や、ためらった者は脱落となる。 このゲームをコンピュータ画面に表示させるプログラムとして作成させることで、コードが書けないプログラマ志願者を見分ける手法をJeff AtwoodがFizzBuzz問題 (FizzBuzz Question) として提唱した。その提唱はインターネットの様々な場所で議論の対象になっている。

Fizz Buzz - Wikipedia

今回はこのFizzBuzz問題でちょっとだけ遊んでみましょう。使用言語はC++です。

Case1: 一般的な解法

#include <bits/stdc++.h>
using namespace std;

int main() {
    for(int i=1; i<101;++i) {
        if(i%15==0) cout << "FizzBuzz" << endl;
        else if(i%3==0) cout << "Fizz" << endl;
        else if(i%5==0) cout << "Buzz" << endl;
        else cout << i << endl;
    }
}

特に説明不要ですね。ループを回して3と5で割り切れるときにはFizzBuzz、3で割り切れるときにはFizz,5で割り切れるときにはBuzz,それ以外の時は数字を出力します。

Case2: if-less

#include <bits/stdc++.h>
using namespace std;

int main() {
    for(int i=1; i<101; ++i) {
        (i%15<1&&puts("FizzBuzz"))
            ||(i%3<1&&puts("Fizz"))
            ||(i%5<1&&puts("Buzz"))
            ||printf("%d\n",i);
    }
}

if文を使わないパターンです。C/C++では&&と||はそれ以上評価が必要なくなるとそこで評価を終了することを利用しています。

Case3: for-less

#include <bits/stdc++.h>
using namespace std;

void fizzbuzz(int i) {
    if(i>100) return;
    (i%15<1&&puts("FizzBuzz"))
        ||(i%3<1&&puts("Fizz"))
        ||(i%5<1&&puts("Buzz"))
        ||printf("%d\n",i);

    fizzbuzz(++i);
}

int main() {
    fizzbuzz(1);
}

再帰を利用してループを使わずに実現しています。あとはさっきと同じです。

Case4: use template

#include <bits/stdc++.h>
using namespace std;

template<class T>
int p(T x) { puts(x); }

template<>
int p(int x) { printf("%d\n", x); }

template<int N>
void fizzbuzz() {
    (N%15<1&&p("FizzBuzz"))
        ||(N%3<1&&p("Fizz"))
        ||(N%5<1&&p("Buzz"))
        ||p(N);

    fizzbuzz<N+1>();
}

template<>
void fizzbuzz<101>() { return; }

int main() {
    fizzbuzz<1>();
}

C++のテンプレートを利用して書き換えています。やってることは同じです。

Case5: golf

#include<ios>
int main(int i){for(;i<101;){printf(i%3?i%5?"%d":"":"Fizz",i);puts(i++%5?"":"Buzz");}}

コードの短さを追求するcode golfという競技があるらしいです。このコードは100バイト強ですが、anarchy golf - FizzBuzzによると一番短いコードで90バイトらしいです。ちなみに、Rubyluaなどのスクリプト言語を利用すればぐっと短くなります。

おまけ: HQ9F+

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++f

HQ9+については各自調べるように。

以上です。