2017-11-01

anond:20171029161516

FizzBuzz問題を読み替える

具体的に1から15までの例で考えてみる。

集合で考えるとして、集合Aを3の倍数、集合Bを5の倍数とする。

U = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }

A = { 3, 6, 9, 12, 15 }

B = { 5, 10, 15 }

A∩B = { 15 }

¬(A∪B) = { 1, 2, 4, 7, 8, 11, 13, 14 }

ベン図は次のようになる。

+-----------U----------+
|                      |
| +---A------+         |
| | 3 6      |         |
| |  9 12 +--+---B---+ |
| |       |15|       | |
| +-------+--+ 5 10  | |
|         |          | |
|         +----------+ |
|                      |
| 1 2 4 7 8 11 13 14   |
+----------------------+

ド・モルガン定理より

¬(A∪B) = ¬A∩¬B

よって、FizzBuzz問題は次のように読み替えられる。

  • (A∩¬B)3の倍数、かつ、5の倍数でなければ "Fizz"を出力
  • (¬A∩B)3の倍数でなく、かつ、5の倍数ならば "Buzz"を出力
  • (A∩B)3の倍数、かつ、5の倍数ならば "FizzBuzz"を出力
  • (¬A∩¬B)3の倍数でなく、かつ、5の倍数でもなければ元の数字を出力

表にしてみる。

5の倍数5の倍数ではない
3の倍数"FizzBuzz""Fizz"
3の倍数ではない"Buzz"元の数字

コード検討

よくあるコードスタイルWikipediaから借りることにして、使用する言語をCとする。

https://ja.wikipedia.org/wiki/Fizz_Buzz

さて、元の論理を愚直に実装するとどうなるだろうか。

#include <stdio.h>

int main(void) {
    int i;
    for (i = 1; i <= 100; i++) {
        if (i % 3 == 0 && i % 5 == 0) {
            printf("FizzBuzz\n");
        }
        if (i % 3 == 0 && i % 5 != 0) {
            printf("Fizz\n");
        }
        if (i % 3 != 0 && i % 5 == 0) {
            printf("Buzz\n");
        }
        if (i % 3 != 0 && i % 5 != 0) {
            printf("%d\n", i);
        }
    }
    return 0;
}

ここで、元増田が発想したような「3の倍数の後に5の倍数を判定させて"Fizz"と"Buzz"を連続出力すれば"FizzBuzz"の段は要らないんじゃね?」作戦を発動する。

"FizzBuzz"の判定をごっそり削り、"Fizz"と"Buzz"の条件が同時に起こることを考慮する。

forの終わりに改行するようにする。

コードを追って、元の論理と合ってるかを確認しておく。

#include <stdio.h>

int main(void) {
    int i;
    for (i = 1; i <= 100; i++) {
        if (i % 3 == 0) {
            printf("Fizz");
        }
        if (i % 5 == 0) {
            printf("Buzz");
        }
        if (i % 3 != 0 && i % 5 != 0) {
            printf("%d", i);
        }
        printf("\n");
    }
    return 0;
}
記事への反応 -
  • いくつかプログラムの参考書というか基本書を読んでみたんだけど大体あるFizzBuzz問題に疑問がある。 記憶にある限り全ての本が15の剰余が0の時FizzBuzz、3の剰余が0の時Fizz、5の剰余が0の...

    • ベン図描くと分かりやすいけど、4つの集合に分ける必要があって A 3の倍数 Fizz B 5の倍数 Buzz A∩B 15の倍数 FizzBuzz ¬(A∪B) それ以外 数字 A,B,A∩Bの3つと、そ...

      • FizzBuzz問題を読み替える 具体的に1から15までの例で考えてみる。 集合で考えるとして、集合Aを3の倍数、集合Bを5の倍数とする。 U = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } A = { 3, 6, 9, 12...

    • 最近の入門書ってそんなにFizzBuzz問題を載せてるの? ひところネットで流行ってたのは知ってるけど。

      • "FizzBuzz"という単語かどうかは置いておいてよくある。

      • むしろ入門書の定番問題だから出来ないのが話題になったんだよ

        • 10年くらい前にアメリカのITの人がブログで、面接にきた技術者のほとんどがFizzBuzz程度も書けないって書いて、それでネットで流行ったんでしょ。 http://www.aoky.net/articles/jeff_atwood/why_cant_pr...

    • 単にそれぞれ改行入ってんじゃないの

      • 伝わってなかったかな? 15の剰余が0の時→FizzBuzz+改行 3の剰余が0の時→Fizz+改行 5の剰余が0の時→Buzz+改行 となってるのが 3の剰余が0の時→Fizz 5の剰余が0の時→Buzz 次のループに行く前...

        • ああごめんごめん fizz,buzzでそれぞれ改行入ってて改行が重複すんじゃないのみたいなよくわからんことを考えていた

    • 入門書だから、3, 5, 15で場合分けでよい 3でFizz、5でBuzz、判定終了後に改行、結果的に15の判定不要はレベル高い

    • ・初心者は改行付きの出力コマンドしか習ってないことが多い Cの場合はprintfが一般的なのでそうでないことも多いけど、 それでも改行文字を入れずにprintfを2回呼ぶと出力が繋がる、と...

記事への反応(ブックマークコメント)

ログイン ユーザー登録
ようこそ ゲスト さん