質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.49%

JavaScript (ES5) 道場コース I「学習コース Ⅲ」の復習7. FizzBuzz問題に挑戦しよう での疑問点

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 628

score 2

課題は以下の通りです。

繰り返し処理を用いて、「FizzBuzz」という有名な問題に挑戦してみましょう!

1から100までの数字を順番に表示してください。 
ただし、 
・その数が3で割り切れるなら
Fizz

・その数が5で割り切れるなら
Buzz

・3でも5でも割り切れるなら
FizzBuzz

をその数字の代わりに表示してください。 

疑問1

なぜ、3の倍数「且つ」5の倍数の "&&" は、if文の中で先頭に書かないとダメなのでしょうか?

疑問2

以下のように記述すると、なぜ、3の倍数、5の倍数、3かつ5の倍数が、それぞれ、Fizz、Buzz、FizzBuzz にならず、数字の間に挟み込まれるのでしょうか?

for(var i = 1; i <= 100; i++ ){
  console.log(i);
  if(i % 3 ===0  && i % 5===0){
    console.log("FizzBuzz");
  }else if (i % 5 ===0){
    console.log("Buzz");
  }else if (i % 3 ===0) {
    console.log("Fizz");
 }
}


イメージ説明

while分を使った場合でも

以下のように記述すると

var i = 1;

while(i <= 100) {
  if(i%3===0 && i%5===0){
    console.log("FizzBuzz");
  }else if(i%3 ===0) {
    console.log("Fizz");
  }else if(i%5 ===0){
    console.log("Buzz");
  }
  console.log(i);
  i ++;
}

コード


こうなります。↓
イメージ説明
なぜでしょうか?

初歩的な質問ですが、回答、よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

なぜ、3の倍数「且つ」5の倍数の "&&" は、if文の中で先頭に書かないとダメなのでしょうか?

javascriptif .. else if .. elseは、条件に合致している場合は以降の条件で判定しないからです。
この例でいうと、「3の倍数「且つ」5の倍数」を先に書いておかないと「3の倍数]もしくは「5の倍数」の条件に引っかかってしまうからです。

例えば

// 条件①
if (i % 5 ===0){
  console.log("Buzz");
// 条件②
}else if (i % 3 ===0) {
  console.log("Fizz");
// 条件③
}else if(i % 3 ===0  && i % 5===0){
  console.log("FizzBuzz");
}

とした場合、条件②条件①が偽(false)の場合にはじめて評価されます。条件③も同様です。
したがって、この例だと15などの値も条件①に先に引っかかってしまうため、"Buzz"と表示されてしまいます。

以下のように記述すると、なぜ、3の倍数、5の倍数、3かつ5の倍数が、それぞれ、Fizz、Buzz、FizzBuzz にならず、数字の間に挟み込まれるのでしょうか?

console.log(i);iの値によらず、必ず実行されるためです。
もし数字の置き換えを実現したい場合はelseを追加してその中で実行するとよいです。

for(var i = 1; i <= 100; i++ ){
  if(i % 3 ===0  && i % 5===0){
    console.log("FizzBuzz");
  }else if (i % 5 ===0){
    console.log("Buzz");
  }else if (i % 3 ===0) {
    console.log("Fizz");
  }
  // 上記のいずれも満たさない場合は数字を表示
  else {
    console.log(i);
  }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/19 14:24 編集

    nekonikiさん、回答ありがとうございます。
    『console.log(i);がiの値によらず、必ず実行されるためです。』は、理解しました。
    ただ、FizzやBuzzが数字の間に挟み込まれるのは不思議です。

    キャンセル

  • 2020/09/19 14:42

    > FizzやBuzzが数字の間に挟み込まれるのは不思議です。
    例えば修正前のソースだとi=3の時に、
    console.log("Fizz");
    のあとに
    console.log(i);
    も実行されているためです。

    キャンセル

0

追記)
FizzBuzz 問題は、様々な処理を訓練するものであり、「1つの回答例だけが正解」というものではありません。
ただ、問題文から「ベン図を想像できる」だけの知識があることが望ましい題材です。

  1. 1から100 の数 という矩形のグループ ... 反復処理(for, while)のブロックで表現
  2. 3で割り切れる という円(Fizz)のグループ ... if 文などで切り分ける
  3. 5で割り切れる という円(Buzz)のグループ ... 同上
  4. 2.3. の重なったグループ ... 同上

ご質問(疑問2)で示されるコードは正しく切り分けができていませんので、if文を再確認する必要があります。

  • if(条件a) { 処理A } .. モシ、「条件aが真」ナラ、「処理A」ヲジッコウ
  • else if(条件b) { 処理B } .. ソウジャナク、「条件bが真」ナラ、「処理B」ヲジッコウ
  • else { 処理C } .. ソウジャナイナラ、「処理C」ヲジッコウ(条件aも条件bも共に偽のとき)
for(var i = 1; i <= 100; i++ ){
  //console.log(i); ... 割り切れるかどうかに関わらず、出力してしまっている
  if(i % 3 ===0  && i % 5===0){
    console.log("FizzBuzz");
  } else if (i % 5 ===0){
    console.log("Buzz");
  } else if (i % 3 ===0) {
    console.log("Fizz");
  } else {
    console.log( i )
  }
}

3の倍数「且つ」5の倍数の "&&" は、if文の中で先頭に書かないとダメなのでしょうか?

問題には要件として示されていませんので、「書かないと駄目」ということはありませんが、
ベン図を見ても分かるように、最も多くの条件を有した領域から消去法で if else を書く手法に過ぎません(重なっている部分を先に処理したほうが、あとで切り分けし直さなくて済むため)。

別段、以下のように、文字列の結合処理に着目した処理も正答です。

for(var i = 1; i <= 100; i++ ){
  var rslt = "";
  if (i % 3 ===0) rslt = "Fizz";
  if (i % 5 ===0) rslt += "Buzz"
  if (rslt === "") rslt += i; // その数字の代わりに表示. 数値でなく数字と示されている
  console.log( rslt );
}

※柔軟な考え方で様々な処理法がある問題ですので、「他人のコードを読む」、「他人にコードを読ませる」といった訓練に使われます。
(追記ここまで


A. 1

if文でelse を使っているからです。

A. 2 

console.log(i) は割り切れるかどうかに関わらず、必ず出力しています。


有名な問題だけあって、検索するとヒットします

if を使わない例を書いてみました。

for ( let i=1; i<=100; ++i ) {
  let
    Fizz = !(i % 3),
    Buzz = !(i % 5),
    Bit = (Fizz<<1) + Buzz,
    out = !(Fizz + Buzz) ? i : (Fizz ? 'Fizz': '') + (Buzz ? 'Buzz': ''),
    out2 = Object.entries({Fizz, Buzz})
        .reduce((a,[k,v])=>(v ? isFinite(a) ? k : a+k : a),i),
    out3 = [i,"Fizz","Buzz","FizzBuzz"][Bit]
  ;
  console.log( out, out2, out3 );
}

主な確認事項:

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/19 14:33

    回答、ありがとうございます。

    『文字列の結合処理に着目した処理』は、難しくて理解できませんでした。

    if (i % 3 ===0) rslt = "Fizz";
    ifとrsltの間は、何も要らないのでしょうか?

    if (i % 5 ===0) rslt += "Buzz"
    +=が理解できません。

    キャンセル

  • 2020/09/19 15:30

    if( 条件 ) { ステートメント1つ } のときには {} を省略できる特徴があります。
    https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/if...else
    で、「statementが複数のときは{} を使ってください」と暗示されています(1つのときは省略できる)

    rslt+= "Buzz" は代入演算子で rslt = rslt + "Buzz" と同じです。
    https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators#Assignment_operators

    キャンセル

  • 2020/09/21 16:48

    上段は知りませんでした。勉強になりました。

    下段の rslt = rslt + "Buzz" は判ります。これにより rslt が "FizzBuzz"というカタチで文字列の連結になるという解釈で合っていますか?

    キャンセル

  • 2020/09/21 16:55

    その 2つめの if 文までに rslt は 3で割り切れなかった "" または 3で割り切れた "Fizz" になっていますので、5で割り切れた場合は "Buzz" または "FizzBuzz" に文字列結合されます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る