定番:FizzBuzz判定
順番を間違えると、片方の答えが一度も出ない
FizzBuzz はプログラミングの練習問題として世界中で使われている定番のお題です。ルールは下記のとおりです。
3でも5でも割り切れる数は"FizzBuzz"3で割り切れる数は"Fizz"5で割り切れる数は"Buzz"- どれでもない数は、その数を文字列にしたもの
繰り返しの道具はまだ持っていないので、今回は 1 つの数だけを判定します。1 件分の処理を関数にしておけば、あとから何件でもそのまま回せます。
このお題がドリルとして優秀なのは、書く順番を間違えると必ず壊れる からです。同じことが起きる形を、スタンプカードで見てみます。
Python
def stamp(n):
if n % 5 == 0:
return "5回目"
elif n % 10 == 0:
return "10回目"
return ""10 を渡しても "10回目" にはなりません。10 % 5 が 0 なので、最初の枝で "5回目" に決まってしまいます。20 も 30 も同じで、2 番目の枝には永遠にたどり着きません。
含まれる側を先に書く
10 の倍数は、必ず 5 の倍数でもあります。つまり 10 の条件は 5 の条件に丸ごと含まれています。含まれる側 (狭い側) を先に書かないと、広い側に飲み込まれます。
Python
def stamp(n):
if n % 10 == 0:
return "10回目"
elif n % 5 == 0:
return "5回目"
return ""これで 10 は "10回目"、5 は "5回目" になります。FizzBuzz でも起きるのはまったく同じことです。3 でも 5 でも割り切れるという条件は、3 だけの条件にも 5 だけの条件にも含まれているので、いちばん厳しい枝から先に並べます。
elifを並べるときは「厳しい条件から、だんだん緩く」と唱えながら書きます。条件分岐のバグの大半はこの順番で起きます。
戻り値の型をそろえる
割り切れるかどうかは剰余の % で調べます。n % 3 が 0 なら 3 で割り切れます。3 でも 5 でも、は and でつなぎます。
数だけを返す枝を数値のままにすると、7 と "7" という別の値が混ざります。この関数は文字列を返すものなので、最後の枝も str で文字列にそろえます。
Python
print(str(7))
print(7 == "7")7 と False が出ます。見た目が同じでも、型が違えば別の値です。あわせて、if n % 3: のように == 0 を書き落とすと「余りが 0 でない」という逆の意味になる点にも気をつけてください。
やってみよう
関数 fizzbuzz_one(n) を実装してください。整数 n を受け取り、上のルールに従った文字列を返します。
どの枝を先に書くかが肝です。書けたら 15 9 10 7 の 4 つを渡して、4 種類の答えがすべて出ることを確かめてみてください。0 を渡すとどうなるかも考えてみると、面白い発見があります。
要件
- 関数名は fizzbuzz_one で、引数は n の 1 つ
- 3 でも 5 でも割り切れるときは "FizzBuzz" を return する
- 3 だけで割り切れるときは "Fizz"、5 だけで割り切れるときは "Buzz" を return する
- どれにも当てはまらないときは str(n) で文字列にして return する
- 3 でも 5 でも割り切れる条件を、他のどの条件よりも先に書く
入出力例
fizzbuzz_one(15) → "FizzBuzz"
fizzbuzz_one(9) → "Fizz"
fizzbuzz_one(10) → "Buzz"
fizzbuzz_one(7) → "7"
fizzbuzz_one(0) → "FizzBuzz"
fizzbuzz_one(1) → "1"
fizzbuzz_one(30) → "FizzBuzz"