---
# System prepended metadata

title: '[2020q3](http://wiki.csie.ncku.edu.tw/sysprog/schedule) Homework4 (quiz4)'
tags: [sysprog2020]

---

---
tags: sysprog2020
---
# [2020q3](http://wiki.csie.ncku.edu.tw/sysprog/schedule) Homework4 (quiz4)
contributed by < `nickchenchj` >
> related links: [2020q3 第 4 週測驗題](https://hackmd.io/@sysprog/2020-quiz4)

## Problem 1
### Task
* Given two integers `x` and `y`, calculate the [Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance).

Below is the implementation of the function that calculates the Hamming distance:
```c=
int hammingDistance(int x, int y) {
    return __builtin_popcount(x OP y);
}
```
#### OP = ?
* `(a)` `|`
* `(b)` `&`
* `(c)` `^`
* `(d)` `+`
* `(e)` `-`

### Solution
According to [GCC Built-in Functions](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html), the description of `__builtin_popcount` is as follows:
> Built-in Function: int __builtin_popcount (unsigned int x)
> * Returns the number of 1-bits in x.

* From the return value `_builtin_popcount(x OP y)`, we can deduce that only pairs of bits in `x` and `y` with the same index but different values will become `1` after `x OP y`. For example, if the LSB in `x` is `0` and the LSB in `y` is `1`, the result of `0 OP 1` will become `1`.

|        `x`        |        `y`        | `x OP y`  |
|:-----------------:|:-----------------:|:---------:|
| ==10==01 01==10== | ==01==01 01==01== | 1100 0011 |

###### Note: 8-bit integer is used for demonstration

* Clearly, OP must be `^`, so the answer to this problem is `(c)` `^`.

:::success
**Answer**
* OP: `^`
:::

---

## Problem 2
### Task
From LeetCode [1483. Kth Ancestor of a Tree Node](https://leetcode.com/problems/kth-ancestor-of-a-tree-node/):
> You are given a tree with n nodes numbered from 0 to n-1 in the form of a parent array where parent[i] is the parent of node i. The root of the tree is node 0.
>
> Implement the function getKthAncestor(int node, int k) to return the k-th ancestor of the given node. If there is no such ancestor, return -1.
>
> The k-th ancestor of a tree node is the k-th node in the path from that node to the root.

#### Example:
![](https://i.imgur.com/gm7B8sp.png)
* Input:
```json
["TreeAncestor","getKthAncestor","getKthAncestor","getKthAncestor"]
[[7,[-1,0,0,1,1,2,2]],[3,1],[5,2],[6,3]]
```

* Output:
```json
[null,1,0,-1]
```
:::info
:information_source: **Explanation**
* `7`: there are `7` nodes in a tree
* `[-1, 0, 0, 1, 1, 2, 2]`: indicates the parents of each node
* `[3, 1]`: gets the `1st` ancestor of node `3` (expected ancestor: `1`)
* `[5, 2]`: gets the `2nd` ancestor of node `5` (expected ancestor: `0`)
* `[6, 3]`: gets the `3rd` ancestor of node `6` (expected ancestor: `-1`)
:::

* Below is the implementation of this problem:

```c=
#include <stdlib.h>

typedef struct {
    AAA;
    int max_level;
} TreeAncestor;

TreeAncestor *treeAncestorCreate(int n, int *parent, int parentSize)
{
    TreeAncestor *obj = malloc(sizeof(TreeAncestor));
    obj->parent = malloc(n * sizeof(int *));

    int max_level = 32 - __builtin_clz(n) + 1;
    for (int i = 0; i < n; i++) {
        obj->parent[i] = malloc(max_level * sizeof(int));
        for (int j = 0; j < max_level; j++)
            obj->parent[i][j] = -1;
    }
    for (int i = 0; i < parentSize; i++)
        obj->parent[i][0] = parent[i];

    for (int j = 1;; j++) {
        int quit = 1;
        for (int i = 0; i < parentSize; i++) {
            obj->parent[i][j] = obj->parent[i][j + BBB] == -1
                                    ? -1
                                    : obj->parent[obj->parent[i][j - 1]][j - 1];
            if (obj->parent[i][j] != -1) quit = 0;
        }
        if (quit) break;
    }
    obj->max_level = max_level - 1;
    return obj;
}

int treeAncestorGetKthAncestor(TreeAncestor *obj, int node, int k)
{
    int max_level = obj->max_level;
    for (int i = 0; i < max_level && node != -1; ++i)
        if (k & (CCC))
            node = obj->parent[node][i];
    return node;
}

void treeAncestorFree(TreeAncestor *obj)
{
    for (int i = 0; i < obj->n; i++)
        free(obj->parent[i]);
    free(obj->parent);
    free(obj);
}
```

#### AAA = ?
* `(a)` `int ***parent`
* `(b)` `int **parent`
* `(c)` `int *parent`

#### BBB = ?
* `(a)` `(-2)`
* `(b)` `(-1)`
* `(c)` `0`
* `(d)` `1`
* `(e)` `2`

#### CCC = ?
* `(a)` `1`
* `(b)` `i`
* `(c)` `i >> 1`
* `(d)` `i >> k`
* `(e)` `k << i`
* `(f)` `1 << i`

### Solution
#### AAA
* By observing `obj->parent = malloc(n * sizeof(int *));` in `treeAncestorCreate`, it is obvious that `parent` is a pointer that points to an array of integer pointers.
* As a result, `AAA` must be `int **parent`.

#### BBB
* To figure out what `BBB` is, we need to know how `treeAncestorCreate` works.
* First, `treeAncestorCreate` creates `obj` and initializes it (`n = 7`):
```c=
TreeAncestor *obj = malloc(sizeof(TreeAncestor));
obj->parent = malloc(n * sizeof(int *));

int max_level = 32 - __builtin_clz(n) + 1;
for (int i = 0; i < n; i++) {
    obj->parent[i] = malloc(max_level * sizeof(int));
    for (int j = 0; j < max_level; j++)
        obj->parent[i][j] = -1;
}
```
* `obj` after initialization:
```graphviz
digraph add_entry{
    graph [pad="0.5", nodesep="0.4", ranksep="0.8"];
    rankdir=LR
    splines=polyline
    node [shape=record]

    parent [
        label="obj->parent"
        shape=plaintext
    ]
    nodes [
        label="{ <n0>n0 }|{ <n1>n1 }|{ <n2>n2 }|{ <n3>n3 }|{ <n4>n4 }|{ <n5>n5 }|{ <n6>n6 }"
    ]
    ancestors_0 [
        xlabel="ancestors of n0"
        label="{ <head>-1 | -1 | -1 | -1 }"
    ]
    ancestors_1 [
        xlabel="ancestors of n1"
        label="{ <head>-1 | -1 | -1 | -1 }"
    ]
    ancestors_2 [
        xlabel="ancestors of n2"
        label="{ <head>-1 | -1 | -1 | -1 }"
    ]
    ancestors_3 [
        xlabel="ancestors of n3"
        label="{ <head>-1 | -1 | -1 | -1}"
    ]
    ancestors_4 [
        xlabel="ancestors of n4"
        label="{ <head>-1 | -1 | -1 | -1}"
    ]
    ancestors_5 [
        xlabel="ancestors of n5"
        label="{ <head>-1 | -1 | -1 | -1}"
    ]
    ancestors_6 [
        xlabel="ancestors of n6"
        label="{ <head>-1 | -1 | -1 | -1}"
    ]
    
    parent -> nodes:n0:w
    nodes:n0:e -> ancestors_0:head:w
    nodes:n1:e -> ancestors_1:head:w
    nodes:n2:e -> ancestors_2:head:w
    nodes:n3:e -> ancestors_3:head:w
    nodes:n4:e -> ancestors_4:head:w
    nodes:n5:e -> ancestors_5:head:w
    nodes:n6:e -> ancestors_6:head:w
} 
```

* Next, `treeAncestorCreate` stores the parents of each node in `obj->parent[i][0]` (`parentSize = 7`):
```c=
for (int i = 0; i < parentSize; i++)
    obj->parent[i][0] = parent[i];
```

* `obj` after storing parents of each node:
```graphviz
digraph add_entry{
    graph [pad="0.5", nodesep="0.4", ranksep="0.8"];
    rankdir=LR
    splines=polyline
    node [shape=record]

    parent [
        label="obj->parent"
        shape=plaintext
    ]
    nodes [
        label="{ <n0>n0 }|{ <n1>n1 }|{ <n2>n2 }|{ <n3>n3 }|{ <n4>n4 }|{ <n5>n5 }|{ <n6>n6 }"
    ]
    ancestors_0 [
        xlabel="ancestors of n0"
        label="{ <head>-1 | -1 | -1 | -1 }"
    ]
    ancestors_1 [
        xlabel="ancestors of n1"
        label="{ <head>0 | -1 | -1 | -1 }"
    ]
    ancestors_2 [
        xlabel="ancestors of n2"
        label="{ <head>0 | -1 | -1 | -1 }"
    ]
    ancestors_3 [
        xlabel="ancestors of n3"
        label="{ <head>1 | -1 | -1 | -1}"
    ]
    ancestors_4 [
        xlabel="ancestors of n4"
        label="{ <head>1 | -1 | -1 | -1}"
    ]
    ancestors_5 [
        xlabel="ancestors of n5"
        label="{ <head>2 | -1 | -1 | -1}"
    ]
    ancestors_6 [
        xlabel="ancestors of n6"
        label="{ <head>2 | -1 | -1 | -1}"
    ]
    
    parent -> nodes:n0:w
    nodes:n0:e -> ancestors_0:head:w
    nodes:n1:e -> ancestors_1:head:w
    nodes:n2:e -> ancestors_2:head:w
    nodes:n3:e -> ancestors_3:head:w
    nodes:n4:e -> ancestors_4:head:w
    nodes:n5:e -> ancestors_5:head:w
    nodes:n6:e -> ancestors_6:head:w
} 
```

* Then, update grandparents of each node, great-grandparents of each node and so on:
```c=
for (int j = 1;; j++) {
    int quit = 1;
    for (int i = 0; i < parentSize; i++) {
        obj->parent[i][j] = obj->parent[i][j + BBB] == -1
                                ? -1
                                : obj->parent[obj->parent[i][j - 1]][j - 1];
        if (obj->parent[i][j] != -1) quit = 0;
    }
    if (quit) break;
}
```

* To find the grandparent of a node, simply find the parent's parent.
* Take ancestors of `n3` for example, say we want to find its grandparent:
    * ancestors of `n3` (original): `{1, -1, -1, -1}`
    * parent of `n3` is `n1` (at `index = 0`)
    * ancestors of `n1`: `{0, -1, -1, -1}`
    * we know that the grandparent of `n3` is the parent of `n1`, which is `n0` (at `index = 0`) in this case
    * update grandparent of `n3` (at `index = 1`) from `-1` to `0`
    * ancestors of `n3` (updated): `{1, 0, -1, -1}`
* From the example above, we can see that the system needs to check if the parent of a node exists before the system carries on finding grandparent of the node.
* Note that the parent node is stored in the element **before** (`current_index - 1`) the element which stores the grandparent node (index of parent: `0`, index of grandparent: `1`).
* Therefore, `BBB` is `(-1)`.
* `obj` (complete):
```graphviz
digraph add_entry{
    graph [pad="0.5", nodesep="0.4", ranksep="0.8"];
    rankdir=LR
    splines=polyline
    node [shape=record]

    parent [
        label="obj->parent"
        shape=plaintext
    ]
    nodes [
        label="{ <n0>n0 }|{ <n1>n1 }|{ <n2>n2 }|{ <n3>n3 }|{ <n4>n4 }|{ <n5>n5 }|{ <n6>n6 }"
    ]
    ancestors_0 [
        xlabel="ancestors of n0"
        label="{ <head>-1 | -1 | -1 | -1 }"
    ]
    ancestors_1 [
        xlabel="ancestors of n1"
        label="{ <head>0 | -1 | -1 | -1 }"
    ]
    ancestors_2 [
        xlabel="ancestors of n2"
        label="{ <head>0 | -1 | -1 | -1 }"
    ]
    ancestors_3 [
        xlabel="ancestors of n3"
        label="{ <head>1 | 0 | -1 | -1}"
    ]
    ancestors_4 [
        xlabel="ancestors of n4"
        label="{ <head>1 | 0 | -1 | -1}"
    ]
    ancestors_5 [
        xlabel="ancestors of n5"
        label="{ <head>2 | 1 | -1 | -1}"
    ]
    ancestors_6 [
        xlabel="ancestors of n6"
        label="{ <head>2 | 1 | -1 | -1}"
    ]
    
    parent -> nodes:n0:w
    nodes:n0:e -> ancestors_0:head:w
    nodes:n1:e -> ancestors_1:head:w
    nodes:n2:e -> ancestors_2:head:w
    nodes:n3:e -> ancestors_3:head:w
    nodes:n4:e -> ancestors_4:head:w
    nodes:n5:e -> ancestors_5:head:w
    nodes:n6:e -> ancestors_6:head:w
} 
```

#### CCC
* code snippet of `treeAncestorGetKthAncestor`:
```c=
int treeAncestorGetKthAncestor(TreeAncestor *obj, int node, int k)
{
    int max_level = obj->max_level;
    for (int i = 0; i < max_level && node != -1; ++i)
        if (k & (CCC))
            node = obj->parent[node][i];
    return node;
}
```

:::success
**Answers**
* AAA: `int **parent`
* BBB: `(-1)`
* CCC: `1 << i`
:::

---

## Problem 3
### Task
* Given a number `n`, write a function that counts from `1` to `n`. 
    * if the current number is a multiple of 3, print out `Fizz`
    * if the number is a multiple of 5, print out `Buzz`
    * if the number is a multiple of 15, print out `FizzBuzz`
    * else, print out the number

* Below is the implementation of the [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz) problem:
```c=
#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;
}
```
#### KK1 = ?
* `(a)` `div5`
* `(b)` `div3`
* `(c)` `2`
* `(d)` `1`

#### KK2 = ?
* `(a)` `0`
* `(b)` `1`
* `(c)` `2`
* `(d)` `div3`
* `(e)` `div5`

#### KK3 = ?
* `(a)` `0`
* `(b)` `1`
* `(c)` `2`
* `(d)` `div3`
* `(e)` `div5`

### Solution
* We create a format string `"FizzBuzz%u"`, and find a way to set the starting index and the string length to get the desired output:
```c 
string literal: "fizzbuzz%u"
        offset:  0   4   8
```

|     Condition     | Starting Index | Length |
|:-----------------:|:--------------:|:------:|
|   `n % 3 == 0`    |       0        |   4    |
|   `n % 5 == 0`    |       4        |   4    |
|   `n % 15 == 0`   |       0        |   8    |
| none of the above |       8        |   2    |

* The `length` is already determined by `length = (2 << div3) << div5`, so let's focus on the starting index.
* Note that the starting index is `(MSG_LEN >> KK1) >> (KK2 << KK3)`. 

#### KK1
* If the current number is neither a multiple of 3 nor a multiple of 5, the starting index must be `MSG_LEN`. We can deduce that `KK1` must be `0` and `KK2 << KK3` must be `0` too. Therefore, the only possible choices for `KK1` are `div5` and `div3`.
* However, `KK1` can't be `div3`. If `KK1` is `div3`, one of `KK2` or `KK3` must be `div5`. If the current number is a multiple of 5 but not a multiple of 3, then `KK2 << KK3` will be greater than `1`, which will make the starting index become lesser than `4`. Hence, `KK1` must be `div5`.

#### KK2
* We already know that `KK1` is `div5`, therefore, one of `KK2` or `KK3` must be `div3`. If `KK3` is `div3` and `KK2` is a non-zero constant, then the result won't match the desired output (where `n % 3 != 0` and `n % 5 != 0`), because `KK2 << KK3` will be greater than `1`, which results in a wrong starting index. As a result, `KK2` must be `div3`.

#### KK3
* After replacing `KK1` and `KK2` with their values, the starting index becomes `(MSG_LEN >> div5) >> (div3 << KK3)`. Then, we take specific conditions into consideration:
* If `n % 3 == 0` but `n % 5 != 0`, then `MSG_LEN` needs to be right-shifted by `4` to become `0`, therefore, `KK3` must be no less than `2`.
* As a result, `KK3` is `2`.

:::success
**Answers**
* KK1: `div5`
* KK2: `div3`
* KK3: `2`
:::

---

## Problem 4
### Task
* Given two numbers `PAGE_QUEUES` and `offset`, observe the code snippet and choose the possible choices for `CASES`:
* possible values of `PAGE_QUEUES`:
    * (1 or 2 or 3 or 4)
    * (5 or 6 or 7 or 8) × (2^n^), where $1 \leq n \leq 14$
* code snippet:
```c=
#include <stdint.h>
#define ffs32(x)  ((__builtin_ffs(x)) - 1)
size_t blockidx;
size_t divident = PAGE_QUEUES;
blockidx = offset >> ffs32(divident);
divident >>= ffs32(divident);
switch (divident) {
    CASES
}
```
From [GCC Built-in Functions](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html):
> Built-in Function: int __builtin_ffs (int x)
> * Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero.

#### CASES = ? (multiple answers)
* `(a)` `2`
* `(b)` `3`
* `(c)` `4`
* `(d)` `5`
* `(e)` `6`
* `(f)` `7`
* `(g)` `8`
* `(i)` `9`
* `(j)` `10`

### Solution
* We know that `ffs32` returns the index of the least significant 1-bit of a number, which is the same result as `__builtin_ctz`.

According to [GCC Built-in Functions](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html):
> Built-in Function: int __builtin_ctz (unsigned int x)
> * Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.

* Therefore, `divident >>= ffs32(divident)` eliminates all zeros before the least significant 1-bit of the number, so the new `divident` must be odd (`LSB = 1`).
* We know that `PAGE_QUEUES` is assigned to `divendent` previously, and the possible values of `PAGE_QUEUES` are:
    * (1 or 2 or 3 or 4)
    * (5 or 6 or 7 or 8) × (2^n^), where $1 \leq n \leq 14$
* As a result, the possible choices must be `3`, `5` and `7`.

:::success
**Answer**
* CASES: `3`, `5` and `7`
:::
