PL/SQLの勉強6 FizzBuzz問題

2022-10-20

2回にわたってプログラミングの基本構造を勉強しました。
以下の3個ですね。

  • 順次
  • 分岐
  • 反復

これらを使う、有名な問題があります。

FizzBuzzをやってみましょう

問題です!

  • 1〜100までの数字を画面に出力します。
  • ただし3の倍数の時は「Fizz」と出力し
  • 5の倍数の時は「Buzz」と出力し
  • 15の倍数の時は「FizzBuzz」と出力します。

実際に自分で考えて、PL/SQLを書いてみましょう。

こんな感じに出力できればOKです。

いろんな答えがあります

僕の持論を語ります。。。

人間の性格はみんな違うように、
プログラムも書く人によって変わってくると思います。

結果が正しく、オーダー通りであれば
それは正解だと思っています。

あとはどれだけ綺麗に・他の人が読みやすく書けるか…

以上のことを頭の隅に置いておきながら
いくつかの解答例を示してみようと思います。

本質的には同じことをやっているかも知れませんが
許してくださいね♪

解答例① – 超基本系

例えばこんな感じに書きます。

begin
  for v_cnt in 1..100 loop
    
    if mod(v_cnt, 15) = 0 then
      dbms_output.put_line('FizzBuzz');
    elsif mod(v_cnt, 3) = 0 then
      dbms_output.put_line('Fizz');
    elsif mod(v_cnt, 5) = 0 then
      dbms_output.put_line('Buzz');
    else
      dbms_output.put_line(v_cnt);
    end if;
    
  end loop;
end;

「mod」は、割り算の余りです。
つまり3で割った余が0の時…という感じに使えます。

ちょっと注意なのが
最初に「15の余りは?」とやっているところです。
3とか5の方を先にやると上手くいきません。。。

解答例② – 出力は1ヶ所派

前職で先輩だったプログラマーさんは
「同じ処理は1ヶ所にまとめなさい!」という方でした。

それも割とシビアに。。。

今回の問題で言うと、
「出力」は1ヶ所でまとめよ!と言うはずです。

それを満たした回答は以下になると思います。

declare
  v_syutsuryoku  varchar2(4000);
begin
  for v_cnt in 1..100 loop
    
    if mod(v_cnt, 15) = 0 then
      v_syutsuryoku := 'FizzBuzz';
    elsif mod(v_cnt, 3) = 0 then
      v_syutsuryoku := 'Fizz';
    elsif mod(v_cnt, 5) = 0 then
      v_syutsuryoku := 'Buzz';
    else
      v_syutsuryoku := v_cnt;
    end if;
    
    dbms_output.put_line(v_syutsuryoku);
    
  end loop;
end;

1つ変数を用意するだけでいいですよね!
慣れれば何も難しいことはありません。

解答例③ – 15の倍数判定はしない

FizzBuzz問題は、いろんな縛りプレイをすることがあります。

その中の1つの例が
「15の倍数判定はしないで作ってみて!」です。

こんな感じに書けるかと思います。

declare
  v_syutsuryoku  varchar2(4000);
begin
  for v_cnt in 1..100 loop
    
    v_syutsuryoku := '';
    
    if mod(v_cnt, 3) = 0 then
      v_syutsuryoku := 'Fizz';
    end if;
    
    if mod(v_cnt, 5) = 0 then
      v_syutsuryoku := v_syutsuryoku || 'Buzz';
    end if;
    
    if v_syutsuryoku is null then
      v_syutsuryoku := v_cnt;
    end if;
    
    dbms_output.put_line(v_syutsuryoku);
    
  end loop;
end;

◆6行目…
出力するための変数を初期化していますね。
これが無いとおかしなことになるので、注意が必要です。

◆16行目…
Oracleでは、空文字の判定は「is null」でします。

どうですか?
1個目の例とは変わってきましたね!

解答例④ – 割り算しない

先ほど「いろんな縛りプレイ」があると書きました。

言っておきながら余り思いつかないのですが
思いつく限りで厄介なものが、割り算をしないパターンです。

割り算ができないとなると…
今の私ならこう書くかなぁ…

declare
  -- 出力用の変数
  v_syutsuryoku  varchar2(4000);
  -- カウンタを用意する(初期値:0)
  v_3  number := 0;  -- 3の倍数用
  v_5  number := 0;  -- 5の倍数用
begin
  for v_cnt in 1..100 loop
    -- 出力用の変数を初期化する
    v_syutsuryoku := '';
    -- カウンタを1UPする
    v_3 := v_3 + 1;
    v_5 := v_5 + 1;
    
    if v_3 = 3 then
      v_syutsuryoku := 'Fizz';
      -- カウンタを初期化する
      v_3 := 0;
    end if;
    
    if v_5 = 5 then
      v_syutsuryoku := v_syutsuryoku || 'Buzz';
      -- カウンタを初期化する
      v_5 := 0;
    end if;
    
    if v_syutsuryoku is null then
      v_syutsuryoku := v_cnt;
    end if;
    
    dbms_output.put_line(v_syutsuryoku);
    
  end loop;
end;

自分でもゴチャゴチャになりそうだし
確認もしたかったので、コメント入れましたw

見ての通りカウンタを準備して
その都度0に戻しながら…ってやってます。

FizzBuzz問題って何に使うの?

4つの解答例を書いてみました。

こんなにやって…
FizzBuzz問題って何のために使うものなの?
って思う方もいるかも知れません。

簡単に言うと、こんな感じです。

あなた、簡単なプログラム書けますか?

例えば面接でこう聞かれたとしましょう。

「書けます!」と答えたとして、

じゃあFizzBuzz問題やってみてよ!

と言われた時に書けないでいると
確実に鼻で笑われます。。。

つまりは初級レベルのプログラムは書けるよね?
の確認に使うのに、すごく良い問題なんです!!

以上ですw

どうでしたか?

初めてやる場合は
いい感じの回答が思い付かない人もいると思います。

でもそれで良いと思っています。

いろんなプログラムを見て、覚えて。
分からなかったら調べて。。。

少しずつスキルを上げていけばいいんです!

何となくこんなロジックもあるよ!と思いついたら
実際にトライしてみてくださいね♪

PL/SQL

Posted by kiri