今回はjavascriptでFizzBuzzをやってみたいと思います。
これを通して、if文やfor文をスラスラ書けるようになれたらいいかな。
お題
1から100までを表示させる。ただし、3の倍数では「Fizz」と表示させる。5の倍数では「Buzz」と表示させる。3と5の倍数では「FizzBuzz」と表示させること。
表示させる箇所はコンソールログ内とする
完成イメージ
javascriptを使ってコンソールログ内に次のような表示をさせるのが今回の目的です。
1
2
Fizz
4
Buzz
Fizz
7
(中略)
13
14
FizzBuzz
16
17
(後略)
どこから始めたらいい?
プログラムを書き慣れている人は頭の中でどこから書き始めたらいいのかなどイメージが出来てたりするんですよね。
でも、プログラムを書き慣れていない人(自分を含めてですが)にとっては、なにをどうしたらいいのかわからない状態。
なのでいきなりプログラムを考えるのではなく、まずはお題をじっくりと分解して、小さなところからひとつずつ作っていきます。
1. 表示させるスペースを確保する
まずjavascriptで書いて得た結果を表示させます。
表示させられなかったら、結果があっているか間違っているかわからないですよね。
<script>
function fizzbuzz(){
console.log(1);
}
fizzbuzz();
</script>
上のjavascriptを動かすと、コンソールログ内に数字の1が表示されます。
function fizzbuzz(){}と言うのは、fizzbuzzを言う関数を作りますというものです。
2. 1から100まで表示してみる
コンソールログの中に数字を表示させることができました。次のステップとして1から100までを表示させたいと思います。
<script>
function fizzbuzz(){
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
}
fizzbuzz();
</script>
上のコードでも頑張れば100まで表示させることはできます。が、もっと数字が大きくなるとできないですよね。それ以前に面倒くさいので違うやり方をしたいと思います。
今回はfor文を使っていきます。
<script>
function fizzbuzz(){
for(i=1; i<=100; i++){
console.log(i);
}
}
fizzbuzz();
</script>
for文の()内で書いてあることを少しだけ解説。
i=1で最初の数字を決めます。
i<=100で最終的な数字を決めます。
iに入っている数字が最終的な数字になるまでi++で1ずつ増やしていきます。
3. 文字に置き換えるための下準備
次に考えたのは、数字で表示させるところとFizzなどの文字に置き換える部分をどう分けるか。
実際に使われる数字・文字は次の4種類
- 数字(3の倍数でも5の倍数でもない場合)
- Fizz(3の倍数の場合)
- Buzz(5の倍数の場合)
- FizzBuzz(3と5の倍数の場合)
数字についてはfor文で出せるようになっているので、ここからは特定の条件の時どうやって文字に置き換えるのかを考えます。
今回はこれをif文で分けていきたいと思います。
if文を書くときは、条件の厳しいものから順番に書くのがいいかなと思っています。上の4つで言えば一番最後のFizzBuzzと表示をさせるのが条件的に厳しそうです。なぜなら「3の倍数である」ということと「5の倍数である」という2つの条件を満たす必要があるから。
次にFizzやBuzzといった文字に置き換えるもの。「3の倍数」もしくは「5の倍数」のいずれかの条件を満たせばいいわけです。
最後に数字を表示させる。これは3の倍数や5の倍数でなくていいので、条件的には一番緩そうです。
4. Fizzを表示させてみる
条件が厳しいものから書くのがいいと言いましたが、難しいのでまずは簡単なFizzを表示させるようにしてみます。
Fizzは3の倍数で表示させるもの。なので、if文で3の倍数時にその数字をFizzと言う文字にしてあげたらいいわけです。
<script>
function fizzbuzz(){
for(i=1; i<=100; i++){
if(i%3 === 0){
console.log('Fizz');
}else{
console.log(i);
}
}
}
fizzbuzz();
</script>
if文を少しだけ解説
i%3===0で余りが0かを調べています。
余りが0の場合は、if文の中に書いてある命令を行います。
条件に当てはまらない場合は、elseの後に書かれている命令を行います。
これで3の倍数の時はFizzと表示されるようになりました。
5. Buzzと表示させてみる
つづいて5の倍数の時にBuzzと表示させてみます。
3の倍数を求めたときと同じく、if文で分けていきます。
<script>
function fizzbuzz(){
for(i=1; i<=100; i++){
if(i%3 === 0){
console.log('Fizz');
}else if(i%5 === 0){
console.log('Buzz');
}else{
console.log(i);
}
}
}
fizzbuzz();
</script>
少しコードが難しくなりました。
簡単に解説をします。
最初に3の倍数かを確認しています。
3の倍数ではなかった場合、次のif文で5の倍数かを確認します。上のコードで言えばelse ifの箇所ですね。
5の倍数だった場合はelse if文の中の命令を、そうでなかった場合はその下のelse内にある命令を行います。
6. FizzBuzzと表示されるようにする
ここから少し難しいです。そしていくつかやり方もあります。
2つ方法を紹介します。
ひとつめは3と5の最小公倍数を使う方法。
最小公倍数、、、懐かしい言葉です(年がバレる。。。)
中学校の数学あたりで習ったと思うのですが、簡単に説明。
0以外の複数の整数の公倍数。その中でも一番小さい数を最小公倍数と言います。
今回の3と5の最小公倍数を例にすると、3の倍数は「3,6,9,12,15,18...」、5の倍数は「5,10,15,20...」ですよね。
3の倍数と5の倍数で共通している数で一番小さい数というと「15」
と言うことで3と5の最小公倍数は15です。
それを踏まえて、先ほどのコードに追加していきます。
<script>
function fizzbuzz(){
for(i=1; i<=100; i++){
if(i%15 === 0){
console.log('FizzBuzz');
}else if(i%3 === 0){
console.log('Fizz');
}else if(i%5 === 0){
console.log('Buzz');
}else{
console.log(i);
}
}
}
fizzbuzz();
</script>
書き方は5の倍数のBuzzを表示させる時と同じです。ひとつelse ifが増えたくらいですかね。
でもそれ以上のポイントがあります。それは書く順番。
「3. 文字に置き換えるための下準備」で書いたとおり、if文は条件が厳しいものから順番に書いていくのがいいと思います。なので、今回はFizzBuzzを表示させるものを一番最初に書きました。
<script>
function fizzbuzz(){
for(i=1; i<=100; i++){
if(i%3 === 0){
console.log('Fizz');
}else if(i%5 === 0){
console.log('Buzz');
}else if(i%15 === 0){
console.log('FizzBuzz');
}else{
console.log(i);
}
}
}
fizzbuzz();
</script>
上のようにFizzBuzzを求めるif文を下に書くと、FizzBuzzとは表示されません。Fizzと表示されます。これは、3と5の倍数の数字がif文を通過するとき、最初のif文である3の倍数をFizzに置き換えるところで条件を満たしてしまうから。条件を満たしてしまうと、その先の処理は行わないんですよ。なので、if文は条件が厳しいものから順番に書くのがいいと思います。
もうひとつの方法ですが、最小公倍数という考え方を使わない方法。
文字に置き換わる条件を思い出してみます。
- 3の倍数の時
- 5の倍数の時
- 3と5の倍数の時
違う言い方をするとこんな感じ
- 3の倍数だけど、5の倍数ではない
- 3の倍数ではないけど、5の倍数
- 3の倍数だし5の倍数でもある
つまり上のような条件をif文で表すことができたら最小公倍数なんていらないですよね。
ということで、上のような条件をif文で書いてみました。
<script>
function fizzbuzz(){
for(i=1; i<=100; i++){
if(i%3 === 0 && i%5 !== 0){
console.log('Fizz');
}else if(i%3 !== 0 && i%5 === 0){
console.log('Buzz');
}else if(i%3 === 0 && i%5 === 0){
console.log('FizzBuzz');
}else{
console.log(i);
}
}
}
fizzbuzz();
</script>
ひとつのif文の中に2つの条件を詰め込んでみました。
この方法だと、FizzBuzzを求めるif文が下になっても大丈夫!
無事、お題をクリアすることができました!!(パチパチパチパチ)
- コンソールログに文字や数字を表示させる
- 1から100まで繰り返す命令を書く
- 3の倍数をFizzに置き換える
- 5の倍数をBuzzに置き換える
- 3と5の倍数をFizzBuzzに置き換える
このようにひとつずつ細かくすると、ひとつひとつのコードが簡単なままなので迷わず書けました。(FizzBuzzのところは少し迷いましたが。。。)
ここから先はもう少しスマートに書く方法です。
違うアプローチでFizzBuzzをやってみる(その1)
今までの方法ではif文で命令を出していましたが、もう少しスマートに書けないものかといろいろ調べてみました。
そこでわかったのが三項演算子というもの。
どうやらif文を使わずに同じような処理ができるみたいです。
ちなみにfor文はそのまま使いますよ。
<script>
function fizzbuzz(){
for(i=1; i<=100; i++){
console.log(i%3 === 0 ? (i%5 === 0 ? 'FizzBuzz' : 'Fizz') : (i%5 === 0 ? 'Buzz' : i));
}
}
fizzbuzz();
</script>
if文を使うと16行もあったコードが9行にまで縮まりました。
その分、なにを書いているのか慣れてない人が見ると分からなくなりましたね。
上のコードを解説。
ところどころ「?」がありますよね。
この?より左側がif文で言う所の条件のようです。
iを3で割ると余りが0のものは始めの格好内の命令を、余りが出るものは後の格好内の命令を処理させています。
始めの格好内にはiを5で割ると余りが0の場合、つまり3の倍数であり5の倍数でもあるので、FizzBuzzと表示するようにという内容です。
始めの格好内にはiを5で割ると余りが出る場合、3の倍数であるが5の倍数ではないので、Fizzと表示するようにという内容です。
後の格好内でiを5で割ると余りが0の場合、つまり3の倍数ではないけど5の倍数であるので、Buzzと表示するようにという内容です。
後の格好内でiを5で割ると余りが出る場合、3の倍数でも5の倍数でもないので、iの値(=数字)を表示するようにという内容です。
違うアプローチでFizzBuzzをやってみる(その2)
上の三項演算子を書いていてふと思ったのが、そもそも3の倍数でなおかつ5の倍数である数字を見つける必要がない気がしてきました。
もう一度おさらいをします。
- 3の倍数のときはFizzと表示
- 5の倍数のときはBuzzと表示
- 3と5の倍数の時はFizzBuzzと表示
3と5の倍数の時って、3の倍数・5の倍数で表示させる文字が連なってるだけなんですよね。
ここを上手に使えば違うパターンのコードが作れそうです。
<script>
function fizzbuzz(){
for(i=1; i<=100; i++){
console.log((i%3 === 0 ? 'Fizz' : '') + (i%5 === 0 ? 'Buzz' : '') || i);
}
}
fizzbuzz();
</script>
文字が連なっているだけという点に注目すると、こんなコードができました。
iを3で割って余りがないときはFizzと表示。余りが出れば何も表示をしない。
同じこと5でも行いました。で、どちらも表示されなかった場合(3の倍数でも5の倍数でもない場合)はiで数字を表示するようにしています。
まとめ
if文やfor文が使えるようになったらと思ってやってみたFizzBuzz。
なんとなくですが、if文やfor文の使い方がわかった気がします。
慣れないと難しそうですが、三項演算子も便利そうですよね。
これからも少しずつjavascriptを書いてみたいと思います。