【JavaScript】Fizz Buzz (paizaランク C 相当) やってみたのと初学者向けに解説

これのやつです。

https://qiita.com/official-events/9ab96aa95d62fe3cbdd7

プログラミングのスキルアップがしたく、イベントに参加してます。

今回、ランクCの問題のため、初学者向けに説明しています。
参考になりましたら幸いです。

# 自己紹介
エンジニア歴8年くらいのWebエンジニアです。
仕事以外のプログラミング歴を合わせると15年くらいプログラミングをしています。

# 問題
https://paiza.jp/works/mondai/c_rank_skillcheck_sample/fizz-buzz

（問題文抜粋）
> 整数 N が入力として与えられます。
> 1からNまでの整数を1から順に表示してください。
> 
> ただし、表示しようとしている数値が、
> ・3の倍数かつ5の倍数のときには、"Fizz Buzz"
> ・3の倍数のときには、"Fizz"
> ・5の倍数のときには、"Buzz"
> を数値の代わりに表示してください。

> <入力される値>
> 入力は以下のフォーマットで与えられます。
> ```
> N
> ```
> N は1以上N以下の整数です。

> <期待する出力>
> 1からNまでの整数を1から順に表示してください。
> 
> ただし、表示しようとしている数値が、
> ・3の倍数かつ5の倍数のときには、"Fizz Buzz"
> ・3の倍数のときには、"Fizz"
> ・5の倍数のときには、"Buzz"
> を数値の代わりに表示してください。

> <入力例1>
> ```
> 5
> ```

> <出力例1>
> ```
> 1
> 2
> Fizz
> 4
> Buzz
> ```

# 考え方
### 問題を整理する
まず問題を整理してみましょう。
まず、「何をするためのコードを書けと言われている？」を考えます。
この問題はFizz Buzzてゲームをコンピュータで再現することが目的のプログラムコードを書けという内容です。

Fizz Buzzとは...

https://ja.wikipedia.org/wiki/Fizz_Buzz#:~:text=Fizz%20Buzz%EF%BC%88%E3%83%95%E3%82%A3%E3%82%BA%E3%83%BB%E3%83%90%E3%82%BA%E3%80%81,%E3%82%8F%E3%82%8C%E3%82%8B%E8%A8%80%E8%91%89%E9%81%8A%E3%81%B3%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82

> <遊び方>
> プレイヤーは円状に座る。最初のプレイヤーは「1」と数字を発言する。次のプレイヤーは直前のプレイヤーの発言した数字に1を足した数字を発言していく。ただし、3の倍数の場合は「Fizz」（Bizz Buzzの場合は「Bizz」）、5の倍数の場合は「Buzz」、3の倍数かつ5の倍数の場合（すなわち15の倍数の場合）は「Fizz Buzz」（Bizz Buzzの場合は「Bizz Buzz」）を数の代わりに発言しなければならない。発言を間違えた者や、ためらった者は脱落となる。

これを今回1人でやった場合のプログラミングの問題になります


整理すると、下記になります。
- プログラムの目的: FizzBuzzゲームをプログラムで再現する
- プログラムの入力: いくつまで行うかの数字
- プログラムの出力: 1から「入力」までの数字をFizz Buzzのルールに沿って出力する

では、処理はどういうものになるでしょう？

### 処理の考え方
一つのやり方として、同じことを人間がした時を想像して、動作や考えることを分析することで、大まかな処理の流れを考える方法があります。

今回処理でしなくてはいけないことは
- 3の倍数かつ5の倍数のときには、"Fizz Buzz"
- 3の倍数のときには、"Fizz"
- 5の倍数のときには、"Buzz"

にすることです。

このプログラムと同じことを人間がする。
もし人間（自分）が行うならどういうことを考え、どういう手順を踏むでしょう。
ちょっと、考えてみましょうか。

まず、他の人からN=5という数字を渡されます。
あなたは、Fizz Buzzのプログラムと同じことをしようとした時、一番最初に何を考えますか？

<br>
(考えてみましょう...)<br>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435274/ae39c771-7c94-f74e-042a-8ff51d63d6b6.png" width="100px" align="center">
<br><br>

一番最初に考えるのは、「1から5まで数えるんだな」と考えましたか？
その後も続けて考えていくと、こういった動作を考えたのではないでしょうか。

![4コマ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435274/c02ab666-98d1-1320-8207-fc7a68df1c4e.png)
<br>
これを文字のフローにしてみましょう。

![1からNまで数える (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435274/add67fad-618e-b28e-481e-01b6cc739ed3.png)
みたいな感じになるでしょうか。

これを、曖昧な言葉でも通じる人間ではなく、機械が処理を実行できるよう、一つ一つを具体的に明確にしましょう。

![1からNまで数える (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435274/5fa9bfcd-8802-5e3a-343e-8e88ffcb55a7.png)

みたいな感じになります。
今回は自分で浮かばなかった場合も、「こんなノリに書き換えればいいんだなぁ」程度に読んでみる感じで大丈夫です。

「処理の考え方」の最後として、作ったフローにプログラムの流れの型を当てはめましょう。
プログラムの流れの型は 3 パターンあります。
![1からNまで数える (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435274/e3a39198-ff9e-c0d4-4b63-d46a4fa19ca6.png)
です。

<dl>
  <dt>順次</dt>
  <dd>ただ上から下に、一文ごとに実行して行きます。(要は、何もないデフォルトの文です)</dd>
  <dt>分岐</dt>
  <dd>条件によって、ルートを分岐させます。(要は、if や　switch 文です)</dd>
  <dt>繰り返し</dt>
  <dd>条件での終わりが来るまで、特定のブロックを繰り返します。(要は、for や while 文です)</dd>
</dl>
これを当てはめていきます。

![1からNまで数える (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435274/be22fc6a-9f65-c0b1-f40b-bb4fc3ea177d.png)
このような感じになります。
この内容を、それぞれのプログラミング言語の命令文に変換していきます。

# 解答コード
<details><summary>解答を見ず、自分で考えたい方の為に折りたたんでます。</summary>

プログラミングは一人一人コードが違うものなので、参考程度に読んでください。

```javascript
process.stdin.resume();
process.stdin.setEncoding('utf8');
// 自分の得意な言語で
// Let's チャレンジ！！
var lines = [];
var reader = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});
reader.on('line', (line) => {
  lines.push(line);
});
reader.on('close', () => {
    const n = Number(lines[0]);
    for(let i=1; i<=n; i++){
        const is3 = i % 3 === 0;
        const is5 = i % 5 === 0;
        
        if(is3 && is5){
            console.log("Fizz Buzz");
        }else if(is3){
            console.log("Fizz");       
        }else if(is5){
            console.log("Buzz");   
        }else{
            console.log(i);   
        }
    }
});
```

実際に書いた部分は`reader.on('close', () => {`以下の部分になります。
(書いたコード)
```javascript
    const n = Number(lines[0]);
    for(let i=1; i<=n; i++){
        const is3 = i % 3 === 0;
        const is5 = i % 5 === 0;
        
        if(is3 && is5){
            console.log("Fizz Buzz");
        }else if(is3){
            console.log("Fizz");       
        }else if(is5){
            console.log("Buzz");   
        }else{
            console.log(i);   
        }
    }
```

### 解説
解答コードに、フローのコメントを書いてたのが下記になります。
```javascript
    // N = 入力値 とする
    // (入力値 は 「文字列型」 のため、「数値型」 に変換しています )
    const n = Number(lines[0]);

    // 【繰り返し】
    // i=1からスタートし、i <= N になるまで i を+1していく
    for(let i=1; i<=n; i++){

        // ( ※ 後で解説します )
        const is3 = i % 3 === 0;
        const is5 = i % 5 === 0;

        // 【分岐】
        if(is3 && is5){
            // i ÷ 3 した時の余りが 0 ( 3の倍数)
            // and i ÷ 5 した時の余りが 0 ( 5の倍数) の場合
            
            console.log("Fizz Buzz");
        }else if(is3){
            // それ以外の場合で、
            // i ÷ 3 した時の余りが 0 ( 3の倍数) の場合
            
            console.log("Fizz");       
        }else if(is5){
            // それ以外の場合で、
            // i ÷ 5 した時の余りが 0 ( 5の倍数) の場合
            
            console.log("Buzz");   
        }else{
            // それ以外の場合、 i ( 数字 )を出力する
            
            console.log(i);   
        }
    }
```

コードを書くにあたって、ただ変換するのではなく、同じことを2回以上行う処理を効率化します。
```javascript
// ( ※ 後で解説します )
const is3 = i % 3 === 0;
const is5 = i % 5 === 0;
```
の箇所ですね。

const `is3` = `i % 3 === 0`; と区切って読みます。
変数`is3` に、「変数 i を÷3した余りが 0 かどうか(`i % 3 === 0`)」の判定の結果を保存します。
変数 `is3` に代入されるのは、真偽値と呼ばれるもので `true` (3の倍数である) か `false` (3の倍数でない)　が代入されます。

同じコードを複数回書かず、効率化することで、プログラムの実行処理が速くなることと、他の人がコードを見た時、読みやすくなる (複数人で開発がしやすくなる)　効果があります。　

</details>

# 感想(まとめ)
記事の内容は以上になります。

「いらすとや」さんの絵ですが、初めてデジタルで4コマ漫画を描いてみたり、どういう内容で書くか、どうしたら伝わるか、四苦八苦しながら記事を書いてみました。

読んでいただき、少しでもプログラミングが身近に感じられたり、もし何か得られるものがありましたら幸いです。
読んでいただき、ありがとうございます。