はじめに
この記事はRubyを使った初歩的なプログラミングのアウトプットの練習をするためのものです。
見辛い点、わかりづらい点などあったらご指摘していただけると幸いです。
FizzBuzz問題について
FizzBuzz問題は、プログラミングの初歩的な問題です。内容は
"1~100の数字を表示させる"
ただしこの時、
"3の倍数の数字の代わりにFizz"
"5の倍数の数字の代わりにBuzz"
"3と5の倍数の数字の代わりにFizzBuzz"
と表示させる。
と言う問題です。
方針
まず1~100の数字を表示させることから考え、表示させる元の数字によって処理を変えていきましょう。
1~100の数字を表示するにはwhile文を使います。元の数字によって処理を変える部分はif文を使います。
1~100の数字の表示
count = 1
while count <= 100
puts count
count += 1
end
countと言う変数を用意し、代入する値を1ずつ増やしながら1から100まで表示させます。次に、このcountが3や5の倍数のときの処理について考えましょう。
条件分岐の部分について
まず3の倍数のときにFizzと表示させる部分を考えます。すなわち、countの値が3の倍数になっている場合、Fizzと表示させれば良いわけです。
変数が3の倍数になると言うことは、変数が3で割り切れれば良いわけなので
if count % 3 == 0
puts "Fizz"
end
と記述することで、countが3の倍数のときはFizzと表示させることができます。
5の倍数についても同様に、
if count % 5 == 0
puts "Buzz"
end
と記述することで、題意を満たすことができます。
次に3と5の倍数について考えます。3と5の倍数とはすなわち15の倍数のことです。
そこで、これまでと同様に
if count % 15 == 0
puts "FizzBuzz"
end
と記述すると題意を満たせそうです。それ以外の場合についてはcountの値をそのまま表示させます。いちいちif文をendで区切ってまたif文を書くのは冗長なので、これまでの記述をelsif文,else文を使ってまとめると、
if count % 3 == 0
puts "Fizz"
elsif count % 5 == 0
puts "Buzz"
elsif count % 15 == 0
puts "FizzBuzz"
else
puts count
end
となります。繰り返しのwhlie文も合わせて記述すると、
count = 1
while count <= 100
if count % 3 == 0
puts "Fizz"
elsif count % 5 == 0
puts "Buzz"
elsif count % 15 == 0
puts "FizzBuzz"
else
puts count
end
count += 1
end
となります。一見これで完成に見えます。しかし、このプログラムを実行しても題意は満たされません。実際にプログラムを実行しても、FizzBuzzの表示が見当たらないはずです。
プログラムの修正
このプログラムの問題点は、15の倍数がFizzと言う表示になり、FizzBuzzと言う表示にならない点にあります。これの原因は、15の倍数であると言うことは同時に3の倍数でもあることと、3の倍数の処理が15の倍数の処理より上に書かれてあることが原因です。
この問題を回避する方法はいくつかあります。自分の思いついた二通りの方法を以下に示します。
条件を変える
一つ目は、FizzとBuzzの表示をする条件がFizzBuzzの表示条件とかぶらないようにするために、それぞれの条件に追記すると言う方法です。
if count % 3 == 0 && count % 15 != 0
puts "Fizz"
elsif count % 5 == 0 && count % 15 != 0
puts "Buzz"
elsif count % 15 == 0
puts "FizzBuzz"
else
puts count
end
条件を読み込む順番を変える
二つ目は、FizzBuzzの表示がされるかどうかを一番に判定することで、他の条件とかぶらないようにする方法です。
15の倍数についての処理を3,5の倍数より先にしてしまえば、FizzBuzzと表示するべきところにはFizzBuzzと。そうでない部分についてはまたそれぞれの条件で表示がなされる。と言う具合です。
if count % 15 == 0
puts "FizzBuzz"
elsif count % 5 == 0
puts "Buzz"
elsif count % 3 == 0
puts "Fizz"
else
puts count
end
コードの分かりやすさなどもを考えると一概にどちらが優れているか、自分では判断できなかったので二つとも紹介をさせていただきました。他にも方法はあると思います。
追記:比べてみると、よりシンプルなコードになっている、後者の方がより良いコードと認識していただけるようです。(コメントより)
感想・まとめ
自分も初心者ですし、できるだけ初心者でも分かりやすい表現を使ったつもりです。”条件を読み込む順番を変える”と言う表現だけで伝わるかどうかがいちばんの不安です。それだけでなぜ問題が解決されるのかの言語化がうまくできている気がしません。自分では理解できた気になっているのですが、説明として適切かどうかは自信がありません。精進していこうと思います。