# 2020q3 Homework4 (quiz4)
contributed by < `chi-ming5566` >
> [測驗題](https://hackmd.io/@sysprog/2020-quiz4)
### 作業要求
* 重新回答[第 4 周測驗題](https://hackmd.io/@sysprog/2020-quiz4),連同附帶的「延伸問題」。
* 比照 [課前測驗參考解答: Q1](https://hackmd.io/s/ByzoiggIb)的模式來撰寫共筆,需要詳細分析自己的思路、參閱的材料 (以第一手材料為主,包含 C 語言規格書的章節),以及==進行相關實驗==。
---
### `測驗一`
```cpp=
int hammingDistance(int x, int y) {
return __builtin_popcount(x OP y);
}
```
兩個位元比較後,相異為1,相同為0,此為XOR,所以
`OP` = `^`。
---
### `測驗三`
從 `div3` 與 `div5` 可知道要判斷的數是 3 還是 5 的倍數,若是,為 1,若否,則為 0。
再來看length的調整
```cpp=
#define MSG_LEN 8
static inline bool is_divisible(uint32_t n, uint64_t M) {
return n * M <= M - 1;
}
static uint64_t M3 = UINT64_C(0xFFFFFFFFFFFFFFFF) / 3 + 1;
static uint64_t M5 = UINT64_C(0xFFFFFFFFFFFFFFFF) / 5 + 1;
int main(int argc, char *argv[]) {
for (size_t i = 1; i <= 100; i++) {
uint8_t div3 = is_divisible(i, M3);
uint8_t div5 = is_divisible(i, M5);
unsigned int length = (2 << div3) << div5;
char fmt[MSG_LEN + 1];
strncpy(fmt, &"FizzBuzz%u"[(MSG_LEN >> KK1) >> (KK2 << KK3)], length);
fmt[length] = '\0';
printf(fmt, i);
printf("\n");
}
return 0;
}
```
由此可知:
* 如果可以整除 3 和 5,length = 2 << 1 << 1 = 8
* 如果可以整除 3 或 5,length = 2 << 1 = 4
* 否則就是 2
而 `KK1` `KK2` `KK3` 則是在問對起點的調整,再來看 "FizzBuzz%u" 這個字串:
* 如果可以整除 “3” 或 “3 和 5”,則要從字串的位置 0 開始複製
* 如果只能整除 5,則要從字串 4 的地方開始複製
* 否則就從 8 的地方開始
由上面幾點可知, (MSG_LEN >> KK1) >> (KK2 << KK3) 經過計算後的結果 start 需如下表:
| div3 | div5 | start |
| ---- | ---- |:----- |
| 0 | 0 | 8 |
| 0 | 1 | 4 |
| 1 | 0 | 0 |
| 1 | 1 | 0 |
可從此表推測出最佳解為 (MSG_LEN >> div5) >> (div3 << 2)。
---
### `測驗四`