これのやつです。
プログラミングのスキルアップがしたく、イベントに参加してます。
今回、ランクCの問題のため、初学者向けに説明しています。
参考になりましたら幸いです。
自己紹介
エンジニア歴8年くらいのWebエンジニアです。
仕事以外のプログラミング歴を合わせると15年くらいプログラミングをしています。
問題
(問題文抜粋)
整数 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とは...
<遊び方>
プレイヤーは円状に座る。最初のプレイヤーは「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のプログラムと同じことをしようとした時、一番最初に何を考えますか?
(考えてみましょう...)
一番最初に考えるのは、「1から5まで数えるんだな」と考えましたか?
その後も続けて考えていくと、こういった動作を考えたのではないでしょうか。
これを、曖昧な言葉でも通じる人間ではなく、機械が処理を実行できるよう、一つ一つを具体的に明確にしましょう。
みたいな感じになります。
今回は自分で浮かばなかった場合も、「こんなノリに書き換えればいいんだなぁ」程度に読んでみる感じで大丈夫です。
「処理の考え方」の最後として、作ったフローにプログラムの流れの型を当てはめましょう。
プログラムの流れの型は 3 パターンあります。
です。
- 順次
- ただ上から下に、一文ごとに実行して行きます。(要は、何もないデフォルトの文です)
- 分岐
- 条件によって、ルートを分岐させます。(要は、if や switch 文です)
- 繰り返し
- 条件での終わりが来るまで、特定のブロックを繰り返します。(要は、for や while 文です)
このような感じになります。
この内容を、それぞれのプログラミング言語の命令文に変換していきます。
解答コード
解答を見ず、自分で考えたい方の為に折りたたんでます。
プログラミングは一人一人コードが違うものなので、参考程度に読んでください。
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', () => {
以下の部分になります。
(書いたコード)
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);
}
}
解説
解答コードに、フローのコメントを書いてたのが下記になります。
// 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回以上行う処理を効率化します。
// ( ※ 後で解説します )
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の倍数でない) が代入されます。
同じコードを複数回書かず、効率化することで、プログラムの実行処理が速くなることと、他の人がコードを見た時、読みやすくなる (複数人で開発がしやすくなる) 効果があります。
感想(まとめ)
記事の内容は以上になります。
「いらすとや」さんの絵ですが、初めてデジタルで4コマ漫画を描いてみたり、どういう内容で書くか、どうしたら伝わるか、四苦八苦しながら記事を書いてみました。
読んでいただき、少しでもプログラミングが身近に感じられたり、もし何か得られるものがありましたら幸いです。
読んでいただき、ありがとうございます。