日々のログ

日々にしたい

FizzBuzz問題を解く

プログラミングの初歩問題のFizzBuzz問題をなんとか解くことができました。

 

概要は

  1. 1から100までの数値を出力すること
  2. ただし条件があり
  3. 3の倍数のときにFizzを出力
  4. 5の倍数のときにBuzzを出力
  5. 3と5の倍数のときにFizzBuzzを出力する

といったシンプルな内容です。

 

回答を見ずにこの問題を解こうとして数日かかりました。

なんというか基礎をしっかり抑えた上で柔軟に考えないと解けないなと…。

私の回答はこうなりました。


<?php
for($i = 1; $i <=100 ; $i++){
if($i % 3 == 0 && $i % 5 == 0){
echo 'FizzBuzz';
}elseif($i % 3 == 0){
echo 'Fizz';
}elseif($i % 5 == 0){
echo 'Buzz';
}else{
echo $i;
}
echo '<br>';
}

?>

 

まずは1~100を出力するためにfor文を利用しました。

 

for ( 変数の初期値 ; 変数の最大値 ; 変数の追加する数値){
繰り返して実行したい処理 ;

 

for文の内容はこういった形になります。

もし変数の初期値を1ではなく50にすれば50スタートになりますし、変数の追加する数

値を+2にすれば2づつ増えていきます。

繰り返して実行したい処理はechoに設定しておけば1~100まで出力してくれます。


このfor文の繰り返して実行したい処理の部分で

今出力している数値が3、5の倍数なのか判断しその結果をechoするという流れになります。


一番つまずいた点がfor文の中にelesを組み込んでもいいという点でした。

この問題でだいぶ自由に設定できるんだなと気が付きました。

 

PHPのforリファレンス

www.php.net

 


まずは倍数に該当する数値を算出します。

3と5の倍数を出力するために代数演算子の%(わり算の余りを出力、名前:剰余)と比較演算子の===(右辺と左辺が同じ時に実行、名前:等しい)を使います。

 

$i % 3 == 0 && $i % 5 == 0

 

3と5の倍数はつまり、3と5で割ったときにあまりが出ない数を指します。

forで出力された数が$iに入り3と5で割られ、あまりが0になったときにTrueされるという内容になります。

&&(名前:論理積)は論理演算子であり、今回は3と5の倍数のときに実行されるように指示する記号となります。

$i % 3 == 0で3の倍数判定、$i % 5 == 0で5の倍数判定、&&でこの2つ公倍数のとき実行!です。

 

3と5の公倍数なのだから15の倍数でいいよねという記事を見かけて自分の頭の硬さに膝から崩れ落ちそうになりました。 

 

PHPリファレンス &&についてなどwww.php.net

 

PHPリファレンス %についてなど

www.php.net

 

PHPリファレンス ===についてなど

www.php.net

 

 

ここまでが倍数かどうか判断する部分になり、Trueのとき実行する文はまた別のものになります。

 

if文とelseまたはelse文を使うことで条件分岐していきます。

 

ifは()の中の条件がtrueの時に実行する関数

 

elseifはifで指定した条件だけでなく複数指定したいときに使います。

 

elseはifとelseifのどちらにも当てはまらないときに実行されます。

 

if($i % 3 == 0 && $i % 5 == 0){
echo 'FizzBuzz';
}elseif($i % 3 == 0){
echo 'Fizz';
}elseif($i % 5 == 0){
echo 'Buzz';
}else{
echo $i;
}

 

まずifで3と5の公倍数両方当てはまるときにFizzBuzzが出力される。

3と5の公倍数に当てはまらなければelseifに移ります。

elseifに移り3の倍数ならばFizzが、3の倍数ではなく5の倍数ならばBuzzが出力されます。

どの倍数にも当てはまらないときはelseになり残りの数値が出力されます。

プログラムは上から順番に処理されるため、最初のifの条件に3と5の公倍数を指定していとこの数値が出力されなくなります。

もし3と5の公倍数を最後にした場合、15の周の時にFizzが出力されてしまいます。

この動作を1~100まで行うことでFizzBizz問題が解けました。

 

ここまでが自己回答なのですが、友人からもっと簡単にできると教えてもらえたのでそちらも載せます。(友人の了承済み

 

  • 1つ目

//ループ
for($i = 1; $i <=100 ; $i++){
// 3と5の公倍数チェック
if($i % 3 === 0 && $i % 5 === 0){
echo "FizzBuzz";
echo "\n";
continue;
}

// 3の倍数チェック
if($i % 3 === 0){
echo "Fizz";
echo "\n";
continue;
}

// 5の倍数チェック
if($i % 5 === 0){
echo "Buzz";
echo "\n";
continue;
}

// どれにも当てはまらなかった場合
echo $i;
echo "\n";
}

内容としてはelseをつかわずに全部ifにすることで簡略化になるそうです。

forで1~100まで出力するのは同じで、for分の中に複数のif文を入れて見やすくなっています。

continueを使うことでプログラムが実行された段階でループから抜ける指示を出せるため動作の簡略化になります。

 

  • 2つ目

//ループ
for($i = 1; $i <=100 ; $i++){
// 出力するデータを入れる変数
$result = "";

// 3の倍数チェック
if($i % 3 === 0){
$result = "Fizz";
}

// 5の倍数チェック
if($i % 5 === 0){
$result .= "Buzz";
}

// どちらにも当てはまらなかった場合
if(strlen($result) === 0){
$result = $i;
}

echo $result;
echo "\n";
}


if文を複数使うのは同じですがもっと簡略化されています。

倍数のときにFizzBuzzを変数へ代入ことで公倍数のifが不要になります。

倍数に当てはまらない場合は、strlenという関数を利用しています。

strlenは文字列の長さを取得します(文字数ではなくバイト数)なので、$resultにあら

かじめ代入されていた0文字でifが実行され数値が出力されます。

柔軟な発想のためには知識が必要だとひしひしと感じます。

 

考え方の参考になります。

qiita.com

 

これはJavaScriptですが仕組みは同じですね

sitest.jp