From 339c8faf3b362898b6f94b22bf1d9e7937db043e Mon Sep 17 00:00:00 2001 From: 1112405062 <1112405062@student.npu.edu.tw> Date: Mon, 22 Jun 2026 18:57:08 +0800 Subject: [PATCH 1/5] test: add process function test cases --- weeks/week-18/solutions/1112405062/process.py | 2 ++ .../solutions/1112405062/test_process.py | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 weeks/week-18/solutions/1112405062/process.py create mode 100644 weeks/week-18/solutions/1112405062/test_process.py diff --git a/weeks/week-18/solutions/1112405062/process.py b/weeks/week-18/solutions/1112405062/process.py new file mode 100644 index 000000000..5ffb09a60 --- /dev/null +++ b/weeks/week-18/solutions/1112405062/process.py @@ -0,0 +1,2 @@ +def process(nums: list[int], D: int = 4) -> list[int]: + return [] diff --git a/weeks/week-18/solutions/1112405062/test_process.py b/weeks/week-18/solutions/1112405062/test_process.py new file mode 100644 index 000000000..0d1143ddb --- /dev/null +++ b/weeks/week-18/solutions/1112405062/test_process.py @@ -0,0 +1,27 @@ +import unittest +from process import process + + +class TestProcess(unittest.TestCase): + + def test_basic_flow(self): + self.assertEqual(process([1, 4, 4, 8, 3], 4), [4, 8]) + + def test_all_filtered_out(self): + self.assertEqual(process([1, 2, 3], 4), []) + + def test_all_duplicates(self): + self.assertEqual(process([4, 4, 4, 4], 4), [4]) + + def test_negative_numbers(self): + self.assertEqual(process([-4, 4, -8, 8], 4), [-8, -4, 4, 8]) + + def test_empty_input(self): + self.assertEqual(process([], 4), []) + + def test_single_element(self): + self.assertEqual(process([4], 4), [4]) + + +if __name__ == '__main__': + unittest.main() From 08b02fc96d00262ca7e372f6720b4e0525f37105 Mon Sep 17 00:00:00 2001 From: 1112405062 <1112405062@student.npu.edu.tw> Date: Mon, 22 Jun 2026 18:57:30 +0800 Subject: [PATCH 2/5] feat: implement process function --- weeks/week-18/solutions/1112405062/process.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/weeks/week-18/solutions/1112405062/process.py b/weeks/week-18/solutions/1112405062/process.py index 5ffb09a60..e9815901e 100644 --- a/weeks/week-18/solutions/1112405062/process.py +++ b/weeks/week-18/solutions/1112405062/process.py @@ -1,2 +1,10 @@ def process(nums: list[int], D: int = 4) -> list[int]: - return [] + seen = set() + deduped = [] + for x in nums: + if x not in seen: + deduped.append(x) + seen.add(x) + filtered = [x for x in deduped if x % D == 0] + filtered.sort() + return filtered From 569eb2d31959e7507abeb2add1d39619a538672a Mon Sep 17 00:00:00 2001 From: 1112405062 <1112405062@student.npu.edu.tw> Date: Mon, 22 Jun 2026 19:15:07 +0800 Subject: [PATCH 3/5] test: add caesar_encrypt test cases --- .../1112405062/Caesar Cipher/caesar.py | 2 ++ .../1112405062/Caesar Cipher/test_caesar.py | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 weeks/week-18/solutions/1112405062/Caesar Cipher/caesar.py create mode 100644 weeks/week-18/solutions/1112405062/Caesar Cipher/test_caesar.py diff --git a/weeks/week-18/solutions/1112405062/Caesar Cipher/caesar.py b/weeks/week-18/solutions/1112405062/Caesar Cipher/caesar.py new file mode 100644 index 000000000..3d88d4330 --- /dev/null +++ b/weeks/week-18/solutions/1112405062/Caesar Cipher/caesar.py @@ -0,0 +1,2 @@ +def caesar_encrypt(text: str, shift: int = 3) -> str: + return "" diff --git a/weeks/week-18/solutions/1112405062/Caesar Cipher/test_caesar.py b/weeks/week-18/solutions/1112405062/Caesar Cipher/test_caesar.py new file mode 100644 index 000000000..d086fd72f --- /dev/null +++ b/weeks/week-18/solutions/1112405062/Caesar Cipher/test_caesar.py @@ -0,0 +1,33 @@ +import unittest +from caesar import caesar_encrypt + + +class TestCaesarEncrypt(unittest.TestCase): + + def test_basic_mixed_case(self): + self.assertEqual(caesar_encrypt("Hello, NPU!"), "Khoor, QSX!") + + def test_lowercase_only(self): + self.assertEqual(caesar_encrypt("abc"), "def") + + def test_uppercase_wrap(self): + self.assertEqual(caesar_encrypt("XYZ"), "ABC") + + def test_with_non_letters(self): + self.assertEqual(caesar_encrypt("abc123! xyz"), "def123! abc") + + def test_empty_string(self): + self.assertEqual(caesar_encrypt(""), "") + + def test_only_non_letters(self): + self.assertEqual(caesar_encrypt("123 !@#"), "123 !@#") + + def test_lowercase_wrap(self): + self.assertEqual(caesar_encrypt("z"), "c") + + def test_uppercase_wrap(self): + self.assertEqual(caesar_encrypt("Z"), "C") + + +if __name__ == '__main__': + unittest.main() From 5a2a3f082cdc6a4d351f9ce004eb273beb313987 Mon Sep 17 00:00:00 2001 From: 1112405062 <1112405062@student.npu.edu.tw> Date: Mon, 22 Jun 2026 19:15:46 +0800 Subject: [PATCH 4/5] feat: implement caesar_encrypt function --- .../solutions/1112405062/Caesar Cipher/caesar.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/weeks/week-18/solutions/1112405062/Caesar Cipher/caesar.py b/weeks/week-18/solutions/1112405062/Caesar Cipher/caesar.py index 3d88d4330..004ddc8f7 100644 --- a/weeks/week-18/solutions/1112405062/Caesar Cipher/caesar.py +++ b/weeks/week-18/solutions/1112405062/Caesar Cipher/caesar.py @@ -1,2 +1,10 @@ def caesar_encrypt(text: str, shift: int = 3) -> str: - return "" + result = [] + for ch in text: + if 'A' <= ch <= 'Z': + result.append(chr((ord(ch) - ord('A') + shift) % 26 + ord('A'))) + elif 'a' <= ch <= 'z': + result.append(chr((ord(ch) - ord('a') + shift) % 26 + ord('a'))) + else: + result.append(ch) + return ''.join(result) From ce41a59f6e5d96aa25854a410f9aea164e3be188 Mon Sep 17 00:00:00 2001 From: 1112405062 <1112405062@student.npu.edu.tw> Date: Mon, 22 Jun 2026 20:01:52 +0800 Subject: [PATCH 5/5] 0622-1112405062 --- .../1112405062/Data Cleaning/AI_LOG.md | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 weeks/week-18/solutions/1112405062/Data Cleaning/AI_LOG.md diff --git a/weeks/week-18/solutions/1112405062/Data Cleaning/AI_LOG.md b/weeks/week-18/solutions/1112405062/Data Cleaning/AI_LOG.md new file mode 100644 index 000000000..b1438cfff --- /dev/null +++ b/weeks/week-18/solutions/1112405062/Data Cleaning/AI_LOG.md @@ -0,0 +1,111 @@ +# AI_LOG.md — 期末考歷程記錄 + +## 題目 +對每一組整數數列,依序完成: +1. 去重複(保留第一次出現的順序) +2. 只保留能被 D 整除的數(D = 4) +3. 由小排到大 + +## 函式簽名 +```python +def process(nums: list[int], D: int = 4) -> list[int] +``` + +## 討論歷程 + +### Step 1 — 規格確認 +- 確認 D = 4 固定 +- 確認多組測資輸入格式(n 行 + 數列行,n=0 結束) +- 輸出格式:空格分隔,無結果時輸出 NONE + +### Step 2 — Test Case 拆解(6 個) +| # | 情境 | 輸入 | 預期輸出 | +|---|------|------|---------| +| 1 | 基本流程 | `[1,4,4,8,3]` | `[4,8]` | +| 2 | 全數篩掉 | `[1,2,3]` | `[]` | +| 3 | 全部重複 | `[4,4,4,4]` | `[4]` | +| 4 | 負數 | `[-4,4,-8,8]` | `[-8,-4,4,8]` | +| 5 | 空輸入 | `[]` | `[]` | +| 6 | 單一元素 | `[4]` | `[4]` | + +### Step 3 — 紅燈確認 +- 測試 6 項:4 項紅燈(預期有值但 stub 回傳 `[]`)、2 項 pass(預期 `[]`) +- commit: `test: add process function test cases` + +### Step 4 — 實作綠燈 +- 去重:用 set + 保持順序 +- 篩選:`x % D == 0` +- 排序:`list.sort()` +- 6/6 測試通過 +- commit: `feat: implement process function` + +## 結果 +- 測試全數通過 ✅ + + +## Caesar Cipher(Caesar Cipher/) + +### 題目 +將每行字串中的英文字母向後移位 SHIFT = 3: +- 大寫 A-Z 內循環 +- 小寫 a-z 內循環 +- 非英文字母原樣保留 + +### 函式簽名 +```python +def caesar_encrypt(text: str, shift: int = 3) -> str +``` + +### Test Case(7 個) +| # | 情境 | 輸入 | 預期輸出 | +|---|------|------|---------| +| 1 | 大小寫混合 | `"Hello, NPU!"` | `"Khoor, QSX!"` | +| 2 | 純小寫 | `"abc"` | `"def"` | +| 3 | 大寫繞圈 | `"XYZ"` | `"ABC"` | +| 4 | 含非字母字元 | `"abc123! xyz"` | `"def123! abc"` | +| 5 | 空字串 | `""` | `""` | +| 6 | 僅非字母 | `"123 !@#"` | `"123 !@#"` | +| 7 | 小寫繞圈 / 大寫繞圈 | `"z"`, `"Z"` | `"c"`, `"C"` | + +### 紅燈確認 +- 7 項測試:6 項紅燈、1 項 pass(空字串) +- commit: `test: add caesar_encrypt test cases` + +### 實作綠燈 +- 用 `ord()` / `chr()` + mod 26 循環移位 +- 7/7 測試通過 +- commit: `feat: implement caesar_encrypt function` + +## ## Hex Digit Root(Hex Digit Root/) + +### 題目 +對每個輸入的十進位非負整數 x,先換算成 base=16 進位,將各位數字相加得到新數;重複此步驟直到結果為個位數(在 base 進位下的個位數),最終以十進位輸出最終的數字根。 +- 多筆輸入,讀到 EOF 結束。 +- 輸入 0 的數字根為 0。 + +### 函式簽名 +```python +def get_hex_digit_root(x: int) -> int + +``` + +### Test Case(4 個) + +| # | 情境 | 輸入 | 預期輸出 | +| --- | --- | --- | --- | +| 1 | 特例處理 | `0` | `0` | +| 2 | 個位數邊界 | `8` | `8` | +| 3 | 基本案例 | `63` | `3` | +| 4 | 大數邊界(Edge Case) | `1000000000` | `10` | + +### 紅燈確認 + +* 4 項測試:4 項紅燈 +* commit: `test: add failing tests for hex digit root` + +### 實作綠燈 + +* 用 `while x >= 16` 進行位數收斂,內部透過 `% 16` 與 `//= 16` 拆解加總各位數數值 +* 搭配 `sys.stdin` 處理多筆輸入直到 EOF 結束 +* 4/4 測試通過 +* commit: `feat: implement hex digit root with eof support`