# 2019q3 Homework2 (quiz2) contributed by < `ArielWu0203` > ###### tags: `linux_2019` * [作業要求](https://hackmd.io/@sysprog/rJn1C5xDS) ## Test 1 考慮下方檔案 `4thought.c` 是 ACM-ICPC 題目 [4 thought](https://open.kattis.com/problems/4thought) 的一個解法,假設程式的輸入符合 [4 thought](https://open.kattis.com/problems/4thought) 的描述,請補完程式碼: ```cpp #include <stdbool.h> #include <stdio.h> enum { opType1 = 0x1 << 0, opType2 = 0x1 << 1, opType3 = 0x1 << 4, opType4 = 0x1 << 5, }; static int operate(int op, int a, int b) { switch (op) { case opType1: return a + b; case opType2: return a - b; case opType3: return a * b; case opType4: return (int) a / b; } return 0; } static char op_to_char(int op) { return "+-*/?"[op - 1]; } static int op_to_prio(int op) { return ((int[]){opType1, opType2, opType3, opType4, -1})[op - 1]; } static int calc(int op1, int op2, int op3) { op1 = op_to_prio(op1); op2 = op_to_prio(op2); op3 = op_to_prio(op3); bool p1 = (op1 & 0x0F) == 0; // = 1 for * or / bool p2 = (op2 & 0x0F) == 0; // else = 0 bool p3 = (op3 & 0x0F) == 0; // (4 + 4 + 4 + 4) or (4 / 4 / 4 / 4) if ((p1 == p2) && (p2 == p3)) return operate(op3, operate(op2, operate(op1, 4, 4), 4), 4); // (4 + 4 + 4 / 4) else if ((p1 == p2) && (p2 < p3)) return operate(op2,operate(op1,4,4),operate(op3,4,4)); // (4 / 4 / 4 + 4) else if ((p1 == p2) && (p2 > p3)) return operate(op3, operate(op2, operate(op1, 4, 4), 4), 4); // (4 + 4 / 4 / 4) else if ((p1 < p2) && (p2 == p3)) return operate(op1, 4, operate(op3, operate(op2, 4, 4), 4)); // (4 / 4 + 4 + 4) else if ((p1 > p2) && (p2 == p3)) return operate(op3, operate(op2, operate(op1, 4, 4), 4), 4); // (4 + 4 / 4 + 4) else if ((p2 > p1) && (p1 == p2)) return operate(op3, operate(op1, 4, operate(op2, 4, 4)), 4); // (4 / 4 + 4 / 4) else if ((p1 > p2) && (p1 == p2)) return operate(op2, operate(op1, 4, 4), operate(op1, 4, 4)); return 0; } int main(void) { int n; scanf("%d", &n); int sol[n]; for (int i = 0; i < n; i++) scanf("%d", &sol[i]); bool validSolution = false; for (int i = 0; i < n; i++) { for (int op1 = 4; op1 > 0; op1--) { for (int op2 = 4; op2 > 0; op2--) { for (int op3 = 4; op3 > 0; op3--) { int sol_checked = calc(op1, op2, op3); if (sol_checked == sol[i]) { validSolution = true; char op1char = op_to_char(op1); char op2char = op_to_char(op2); char op3char = op_to_char(op3); printf("4 %c 4 %c 4 %c 4 = %d\n", op1char, op2char, op3char, sol[i]); op1 = -1; op2 = -1; op3 = -1; break; } } } } if (!validSolution) printf("no solution\n"); validSolution = false; } return 0; } ``` :::success 延伸問題: 1. 解釋程式運作的原理和推敲背後的思路; 2. 探討 [4 thought](https://open.kattis.com/problems/4thought) 組合出來的數值分佈,並且透過數論解釋; 3. 提出得以改善上述程式碼執行效率的方案,著手分析和實作; ::: ## Test 2 考慮以下程式碼 (`fitbits.c`) 可檢驗輸入的整數 `x` 是否可用 `n` 個位元來表示,例如 (x = 4, n = 9) 要回傳 `true`, 當 (x = 4, n = 2) 回傳 `false`。 ```cpp #include <stdbool.h> bool fit_bits(int x, int n) { int mask = (-1) & (1 << (n-1)); int sign = 1 & (x >> 31); x = (x & mask) >> (n-1); x = ~((sign-1)^x); return (bool) !x; } ``` :::success 延伸問題: 在重視資訊安全的專案中,找出類似用法的程式碼,予以解說並進行相關 information leaks 的實驗 ::: ## Test 3 考慮以下程式碼 (`is-less-equal.c`) 可檢驗輸入的整數 `x` 和 `y`,是否存在 $x <= y$ 的關係。例如 (x = 4, n = 4) 要回傳 `true`, 當 (x = 14, n = 9) 回傳 `false`。 ```cpp #include <stdbool.h> bool is_leq(int x, int y) { int sign_x = (x>>31) & 1; int sign_y = (y>>31) & 1; int diff = sign_x ^ sign_y; int diff_leq = diff & sign_x; // different sign & x is negative int leq = (!diff) & !(y + (~x+1) >> 31) ; // same sign return (leq | diff_leq); } ``` :::success 延伸問題: 在重視資訊安全的專案中,找出類似用法的程式碼,予以解說並進行相關 information leaks 的實驗 ::: ## Test 4