---
# System prepended metadata

title: 'Create a for loop that iterates up to 100 while outputting "fizz" at multiples of 3, "buzz" at multiples of 5 and "fizzbuzz" at multiples of 3 and 5.'

---

# Create a for loop that iterates up to 100 while outputting "fizz" at multiples of 3, "buzz" at multiples of 5 and "fizzbuzz" at multiples of 3 and 5.
> FizzBuzz 是一個經典的編程面試考題。
> 建立一個for迴圈，印出從1~100，若為"3的倍數顯示 Fizz "、若為"5的倍數顯示 Buzz "、若同為3和5的倍數顯示 FizzBuzz"

## 利用餘數的觀念解決問題:
> 在算術中，當兩個整數相除的結果不能以整數商表示時，餘數便是其「餘留下的量」。**當餘數為零時，被稱為整除。**
> 程式執行時，順序是一行一行下來。所以最嚴格的條件，應該要放在前面優先執行。**當 i 對同為3和5的倍數 取餘數，餘數為零時，則顯示"FizzBuzz"** 應寫在 if-else 的判斷式的前面。


## 各式各樣的解法:
> 題目建議在面試時選擇清楚好理解的方式，程式比較長也沒關係。

### 較常見的if else:
#### 版本 1:
```javascript=
const n = 100;
for (var i=1; i <= n; 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);
}
```
:sunflower:**程式步驟:**
1. 先令某數為 i
1. 當 i 對 同為3和5的倍數 取餘數，餘數為零時，則顯示"FizzBuzz"
1. 當 i 對 3 取餘數，餘數為零時，則顯示"Fizz"
1. 當 i 對 5 取餘數，餘數為零時，則顯示"Buzz"

:::info
答案印出來是對的!
但不建議使用(3X5)15的倍數去解題，因為==3的倍數印Fizz==、==5的倍數印Buzz==，這兩個條件是獨立的，直接相乘的話程式的可讀性會降低。
如果多了其他的條件，就要多寫。(eg. 7的倍數印woof， i%7、i%21、i%35、i%105)
:::

#### 版本1 修正:
```javascript=
const n = 100;
for (var i=1; i <= n; i++){
    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");
    else
        console.log(i);
}
```
<hr>

#### 版本 2:
```javascript=
const n = 100;
for(let i = 1; i <= n; i++){
  let result = '';
  if(i%3 === 0){
    result += 'Fizz'
  }
  if(i%5 === 0){
    result += 'Buzz'
  }
  if(i%7 === 0){
    result += '777'
  } //直接加一個if判斷解決版本1的問題
  if(result.length >0){
    console.log(result);
  }
  else {
    console.log(i);
  }
}
```
有新增的條件只要多增加一組if判斷就可以，原理是用空的字串 result ，遇到符合條件的就疊加上去。

<hr>
<hr>

### 利用三元運算子:
```
condition ? exprIfTrue : exprIfFalse
```
[Ternary(Conditional)operator 三元(條件) 運算子](https://hackmd.io/@pikachuchu/B1S8bNVet)
#### 版本1 :
```javascript=
for (var i = 1; i <= 100; i++) {
  str = (i % 5 == 0 && i % 3 == 0) ? "FizzBuzz" : (i % 3 == 0 ? "Fizz" : (i % 5 == 0) ? "Buzz" : i);
  console.log(str);
}
```
:sunflower:**詳細步驟:**
1. 建立一個For迴圈從1數到100
1. 當 i **對 同為3和5的倍數 取餘數**。餘數為0時，執行"FizzBuzz"，餘數不為0，執行``(i % 3 == 0 ? "Fizz" : (i % 5 == 0) ? "Buzz" : i)``
1. 當 i **對 3 取餘數**。餘數為0時，執行`"Fizz"`，餘數不為0，執行``(i % 5 == 0)? "Buzz" : i``
1. 當 i **對 5 取餘數**，餘數為0時，執行`"Buzz"`，餘數不為0，執行`i`。

<hr>

#### 版本2 :

```javascript=
for (var i = 1; i <= 100; i++) {
  var f = i % 3 == 0, b = i % 5 == 0;
  console.log(f ?( b ? "FizzBuzz" : "Fizz" ):( b ? "Buzz" : i));
}
```
:sunflower:**詳細步驟:**

==當程式跑 i=15 的情況:==

1. 建立一個For迴圈從1數到100
1. `f ?( b ? "FizzBuzz" : "Fizz" ):( b ? "Buzz" : i)`，餘數為0時，執行`( b ? "FizzBuzz" : "Fizz" )`，~~餘數不為0，執行`( b ? "Buzz" : i)`~~。
3.  `b ? "FizzBuzz" : "Fizz"`，餘數為0時，執行`"FizzBuzz"`，~~餘數不為0，執行`"Fizz"`。~~

<hr>

#### 版本3 : 目前看到最簡潔的寫法
```javascript=
for(i=0;i<100;)console.log((++i%3?'':'Fizz')+(i%5?'':'Buzz')||i)
```
:::info
一般情況下沒問題，但在“嚴格模式”(use strict)下若省去`let`，會跑錯。*ReferenceError: i is not defined*
:::

:sunflower:**運用到的觀念:**
| Operator     | Usage                                                                                                                                          | Description                                                                                                                                      |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| 增加 (++)    | 一元運算子。 將運算元增加1。假如使用在運算元之前 ``(++x)``，運算元會回傳增加1後的值;假如使用在運算元之後。 ``(x++)``， 會回傳運算元加1前的值。 | 假如 x是 3，那 ``++x`` 將把 x 設定為 4 並回傳 4，而 ``x++`` 會回傳 3 ， 接著才把 x 設定為 4。                                                    |
| OR (ll)      | 運算式1 ll 運算式2                                                                                                                             | 假如 運算式1 可以被轉換成 true的話，回傳 運算式1; 否則，回傳 運算式2。 因此，**ll在 兩個運算元有任一個是True 時就會回傳 True，否則回傳 false**。 |
| Falsy values | ![](https://i.imgur.com/vZKj0mQ.png)                                                                                                           | **false values以外的都是truthy values**                                                                               |




:sunflower:**詳細步驟:**

==程式跑第一次 `i=0` 的情況:==

**先來處理console.log前段的部分:**
1. `++i%3 ? '' : 'Fizz'` ------------> 使用到三元運算子的觀念 `condition ? value if true : value if false`。 如果為 true執行 `''` ，false執行`Fizz`。 

2.  `++i%3`  ------------> 運用到增加運算符 ++的觀念。
我們第一個執行的i為1 (++i使0變1)。 1%3 會得到 1，運算式會變成 `1 ? '' : 'fizz'`，1為truthy value，

![](https://i.imgur.com/1vZ2tMB.png)

所以會變成`true ? '' : 'fizz'`，最終得出`''`。

3. 整段程式變成
```javascript=
for(let i=0;i<100;)
  console.log(
    ( '' ) + ( i%5 ? '' : 'buzz' ) || i
    )
```

**接著處理console.log後段的部分:**
1. `i%5 ? '' : 'buzz'` ----------------> 一樣使用到三元運算子的觀念 `condition ? value if true : value if false`。 如果為 true執行 '' ，flase執行buzz。 
2. `i%5` 這邊的i帶入1， 1%5 會得到1，運算式會變成 `1 ? '' : 'buzz'`，1為truthy value
![](https://i.imgur.com/ZfXeMBG.png)
所以會變成`true ? '' : 'buzz'`，最終得出`''`。

程式經過了上面兩段步驟被簡化成
```javascript=
console.log( '' + '' || i )
```
由於空字串加空字串仍會是空字串，程式會再進一步簡化成
```javascript=
console.log( '' || i )
```
我們會運用到OR(||)的觀念，由於空字串是 JavaScript 中的七個falsy values之一，程式會跳過空字串執行下一個運算元(operand)，這邊指的是i。
```javascript=
console.log(i) //1
```

分開操作看看結果:
https://codepen.io/natalia0604/pen/PojqpQP

==當程式跑 `i=14` 的情況:==
```javascript=
for(let i=0;i<100;)
  console.log(
    ( ++i%3 ? '' : 'fizz' ) + ( i%5 ? '' : 'buzz' ) || i
  )
```
* `++i%3` 這邊的i會變成15， 運算式會變成`15 % 3 ? '' : 'fizz'`，`15%3` 會得到0，
* `i%5` 這邊的i帶入15， 運算式會變成`15 % 5 ? '' : 'buzz'`，`15%5` 會得到0。
![](https://i.imgur.com/qVtpJ4e.png)

0為falsy value，所以程式會變成
```javascript=
console.log( 'fizz' + 'buzz' || i )
```
再簡化成
```javascript=
console.log( 'fizzbuzz' || i )
```
由於非空字符串('fizzbuzz')是 truthy value，OR(||) 將短路並返回 'fizzbuzz' 
```javascript=
console.log('fizzbuzz')
```
<hr>
<hr>

### 搭配forEach
``` javascript=
var multipliers = [
  [3, "Fizz"],
  [5, "Buzz"]
]

for (let i = 1; i <= 100; i++) {
  let output = "";
  
  multipliers.forEach(function(item) {
     if (i % item[0] === 0) {
       output += item[1];
     }
  }); 

  console.log(output || i);
}
```
:sunflower:**詳細步驟:**

* `item[0]`指的是multipers的3、5，所以每當`i++`時都會讓  i對3和5取餘數。
* 如果`i%item[0]=== 0`成立就會將`item[1]`的字串(指的是"Fizz"和"Buzz"
)加入`output`裡，接著執行 `console.log(output || i)`
* 依照OR(||)的規則，`output`不為空字串時，會回傳`console.log(output)`。


**分開操作看看結果:**

==當程式跑 `i=15` 的情況:==
```javascript=
var multipliers = [
  [3, "Fizz"],
  [5, "Buzz"]
]

for (let i = 15; i <= 15; i++) {
  let output = "";

  multipliers.forEach(function(item) {
    console.log(item[0]);
     if (i % item[0] === 0) {
       output += item[1];
     }
  }); 

  console.log(output || i);
}
```
<hr>
<hr>

### 搭配map
#### 版本1 :
```javascript=
[...Array(100).keys()].map(n => ++n).map(n => console.log(`${n % 3 ? '' : 'Fizz'}${n % 5 ? '' : 'Buzz'}` || n));
```


| Column 1 | Column 2 | Column 3 |
| -------- | -------- | -------- |
| Template literals (樣板字面值)   | ${expression}    | 可以放入變數或任何的表達式。 eg.( ${3+4} 、 \${2*(numA + numB)} ) 。 當 \${'one'}${'two'} 可以合併字串，'onetwo'。|

```javascript=
// ${}${}
let a = 'apple';
let b = 'banana';
console.log(`${a}${b}`); //"applebanana"
```

:sunflower:**詳細步驟:**

==簡化成跑到15的版本==
```javascript=
[...Array(15).keys()].map(n => ++n).map(n => console.log(`${n % 3 ? '' : 'Fizz'}${n % 5 ? '' : 'Buzz'}` || n));
```
* `[...Array(15).keys()].map(n => ++n)` ------------> 會得到一個從1-15的陣[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
* 用map()去遍歷array裡的每一個元素，跑console.log裡的判斷式。

```javascript=
// 當n=1
console.log(`${n % 3 ? '' : 'Fizz'}${n % 5 ? '' : 'Buzz'}` || n)
會簡化成
console.log(${''} || n)
再簡化成
console.log(n)

//當n=3
console.log(`${n % 3 ? '' : 'Fizz'}${n % 5 ? '' : 'Buzz'}` || n)
會簡化成
console.log(${'Fizz'}${''} || n)
再簡化成
console.log('Fizz')

//當n=15
console.log(`${n % 3 ? '' : 'Fizz'}${n % 5 ? '' : 'Buzz'}` || n)
會簡化成
console.log(${'Fizz'}${'Buzz'} || n)
再簡化成
console.log('FizzBuzz')
```
<hr>

#### 版本 2:

```javascript=
a=[,,,'Fizz',,'Buzz']
Array.from(' '.repeat(101)).map((b,i)=>i&&console.log(
a.map((c,j)=>i%j?'':c).join('')||i
))
```
:sunflower:**詳細步驟:**

先看前半段
```javascript=
a=   [ , , ,'Fizz', ,'Buzz']
index[0,1,2,   3  ,4,   5  ]

Array.from() 可以產生array的方法
Array.from(' '.repeat(101)) 會印出101個空字串的array
Array.from(' '.repeat(101)).map((b,i)=>i 會印出0-100的array
```
再來看console.log()

==當程式跑 `i=15` 的情況:==
```javascript=
// 當 i=15
a.map((value,index)=>i%index?'':value).join('')||i

a.map(("",0)=>15%0?'':"")  //''
a.map(("",1)=>15%1?'':"")  //''
a.map(("",2)=>15%2?'':"")  //''
a.map(('Fizz',3)=>15%3?'':'Fizz') //'Fizz'
a.map(("",4)=>15%4?'':"") //''
a.map(('Buzz',5)=>15%5?'':'Buzz') //'Buzz'
join('') ------------> 'FizzBuzz'
a.map('FizzBuzz'||i) //'FizzBuzz'

```
<hr>

#### 版本 3:
```javascript=
console.log(Array(100).fill(1).map(function(val, index) {
    index++;
    if (index % 15 == 0){return "FizzBuzz";}
    if (index % 3 == 0){return "Fizz";}
    if (index % 5 == 0){return "Buzz";}
    return index;
  }).join('\n'))
```
:sunflower:**詳細步驟:**

==簡化成跑到15的版本==

* `Array(15).fill(1)` -----------------> 會得到[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

* `Array(15).fill(1).map()`
```
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
index[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ]
```
```javascript=
function(val, index) {
    index++;
    if (index % 3 == 0 && index % 5  == 0){return "FizzBuzz";}
    if (index % 3 == 0){return "Fizz";}
    if (index % 5 == 0){return "Buzz";}
    return index;
  }).join('\n'))
```


![](https://i.imgur.com/kiibpib.png)
[What is Array.apply actually doing](https://stackoverflow.com/questions/25512771/what-is-array-apply-actually-doing)

[codepen](https://codepen.io/phoebe4561/pen/yLXLQEM?editors=0012)

## 小結:
可以從 考慮**拓展性、效率**的角度去進化你的fizzbuzz程式。
還有很多有創意，上面沒提到的解法，可以點進去慢慢看
[FizzBuzz JavaScript solution](https://gist.github.com/jaysonrowe/1592432)

## 參考資料:
[JavaScript — Breaking Down The Shortest Possible FizzBuzz Answer](https://codeburst.io/javascript-breaking-down-the-shortest-possible-fizzbuzz-answer-94a0ad9d128a)
[簡單的 FizzBuzz 藏有 深度(google 面試題)](https://bear-1111.medium.com/%E7%B0%A1%E5%96%AE%E7%9A%84-fizzbuzz-%E8%97%8F%E6%9C%89-%E6%B7%B1%E5%BA%A6-google-%E9%9D%A2%E8%A9%A6%E9%A1%8C-f5e66e3a97be)
https://stackoverflow.com/questions/25512771/what-is-array-apply-actually-doing