Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions weeks/week-18/solutions/1114405013/p1_data_cleaning/AI_LOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
## 開工前資訊檢查表

### ① 函式簽名

本題不是只寫函式,而是整支程式讀 stdin、印 stdout。
主要程式檔為 `main.py`。
程式從標準輸入讀入多組數字資料,依照題目規則處理後輸出結果。

### ② 輸入邊界

輸入讀到 EOF 結束。
每一組資料可能包含多個整數。
數字中可能有重複值,需要先去除重複。
我的學號參數為 D = 5,因此要篩選可以被 5 整除的數字。

### ③ 例外處理

題目主要處理合法整數輸入。
如果某一組資料沒有任何數字可以被 D = 5 整除,輸出 `NONE`。
如果輸入為空,程式不輸出任何內容。
不額外擴充題目沒有要求的非法格式處理。

### ④ edge case

我設計「沒有任何數字可以被 5 整除」作為 edge case。
例如第一組 sample:`4 7 4 2 9 2 6 7`,去重後為 `4 7 2 9 6`,沒有任何數字可以被 5 整除,所以輸出 `NONE`。

### ⑤ 驗收標準

D 固定為 5。
每一組資料要先去除重複數字,再篩選可以被 5 整除的數字,最後由小到大排序輸出。
如果沒有符合條件的數字,輸出 `NONE`。
我會用 `python -m unittest -v test_data_cleaning.py` 驗證。
測試必須先紅燈,再完成 `main.py` 實作後變綠燈。
輸出必須和 expected output 完全一致,包含換行。

## 我問了 AI 什麼

1. 請 AI 根據題目設計至少 3 個 test case,其中至少 1 個是 edge case。
2. 我補充本題的固定參數 `D = 5`。
3. 我確認本題要寫成「整支程式讀 stdin / 印 stdout」,不是只寫函式。
4. 我請 AI 幫我設計 `unittest` 測試案例,但先不要寫正式實作。
5. 我詢問測試檔案名稱、如何執行測試,以及 red test 後如何進入實作。
6. 我完成 red test 和 `test:` commit 後,請 AI 放入正式程式。

## AI 給了我什麼

1. AI 幫我整理了 4 個測試情境:
- 一般案例
- 邊界案例
- 特殊案例
- edge case
2. AI 提供了 `test_data_cleaning.py`,用 `unittest` 模擬 stdin / stdout。
3. AI 說明如何執行測試:

```bash
python -m unittest -v test_data_cleaning.py
## 我改了什麼
我設定本題的固定參數為 D = 5。

我決定程式採用 stdin / stdout 格式。

我建立作業資料夾:

text
weeks/week-18/solutions/1114405013/p1_data_cleaning/
我放入測試檔:

text
test_data_cleaning.py
我先執行測試,確認 red test 失敗後,完成 test: commit。

我放入正式程式:

text
main.py
我再次執行 unittest,確認測試全部通過。
41 changes: 41 additions & 0 deletions weeks/week-18/solutions/1114405013/p1_data_cleaning/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import sys


D = 5


def main():
lines = sys.stdin.read().splitlines()
outputs = []
index = 0

while index < len(lines):
n = int(lines[index])
index += 1

if n == 0:
break

numbers = list(map(int, lines[index].split()))
index += 1

seen = set()
cleaned = []
for number in numbers:
if number not in seen:
seen.add(number)
if number % D == 0:
cleaned.append(number)

if cleaned:
outputs.append(" ".join(map(str, sorted(cleaned))))
else:
outputs.append("NONE")

sys.stdout.write("\n".join(outputs))
if outputs:
sys.stdout.write("\n")


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import io
import unittest
from unittest.mock import patch

import main


class TestDataCleaningProgram(unittest.TestCase):
def run_program(self, input_text):
fake_stdout = io.StringIO()
with patch("sys.stdin", io.StringIO(input_text)), patch("sys.stdout", fake_stdout):
main.main()
return fake_stdout.getvalue()

def test_normal_case_removes_duplicates_filters_multiples_of_5_and_sorts(self):
input_text = """8
10 3 5 10 20 7 5 15
0
"""
expected = """5 10 15 20
"""
self.assertEqual(self.run_program(input_text), expected)

def test_boundary_case_single_valid_number(self):
input_text = """1
5
0
"""
expected = """5
"""
self.assertEqual(self.run_program(input_text), expected)

def test_special_case_outputs_none_when_no_number_matches(self):
input_text = """4
1 2 3 4
0
"""
expected = """NONE
"""
self.assertEqual(self.run_program(input_text), expected)

def test_edge_case_handles_negative_numbers_zero_and_duplicates(self):
input_text = """7
-10 0 -10 25 12 0 -5
0
"""
expected = """-10 -5 0 25
"""
self.assertEqual(self.run_program(input_text), expected)


if __name__ == "__main__":
unittest.main()
67 changes: 67 additions & 0 deletions weeks/week-18/solutions/1114405013/p2_caesar_cipher/AI_LOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# AI_LOG

## 開工前資訊檢查表

### ① 函式簽名

本題不是只寫函式,而是整支程式讀 stdin、印 stdout。
主要程式檔為 `main.py`。
程式從標準輸入讀入多行文字,處理後輸出多行文字。

### ② 輸入邊界

輸入可能有多行文字,讀到 EOF 結束。
每一行都要處理,輸出行數要和輸入行數相同。
文字中可能包含大寫英文字母、小寫英文字母、空白、標點符號、數字。

### ③ 例外處理

非英文字母不做位移,直接保留原字元。
空白、逗號、驚嘆號、數字與其他符號都保持不變。
如果輸入為空,程式不輸出任何內容。

### ④ edge case

我測試 `wxyz WXYZ`,因為 SHIFT = 4 時需要從 z/Z 循環回 a/A。
預期輸出是 `abcd ABCD`。

### ⑤ 驗收標準

SHIFT 固定為 4。
大寫 A-Z 往後位移 4 格,小寫 a-z 往後位移 4 格。
超過 Z 或 z 要循環回開頭。
非英文字母保持不變。
輸出必須和 expected output 完全一致,包含換行。

---


## 我問了 AI 什麼

1. 我請 AI 根據第二題 Caesar Cipher 題目,先設計 unittest 測試。
2. 我告訴 AI 這題是整支程式讀 stdin、印 stdout,不是只寫函式。
3. 我提供題目規格:SHIFT 固定為 4、大小寫英文字母要位移、非英文字母保持不變、讀到 EOF 結束。
4. 我要求 AI 先只產生測試檔,不要寫正式實作。
5. 我後來要求把測試檔名稱改成 `test_caesar_cipher.py`。
6. 我確認 red test 失敗,並完成 `test:` commit 後,請 AI 幫我建立 `main.py`。

## AI 給了我什麼

1. AI 幫我設計了 3 個 unittest 測試案例:
- 一般案例:測大小寫字母位移與標點保留。
- edge case:測 `z/Z` 超過後循環回 `a/A`。
- 特殊案例:測數字、標點、空白行保持不變。
2. AI 建立了測試檔:

```text
test_caesar_cipher.py


## 我改了什麼

我確認本題的 SHIFT 是 4,不是 sample 上的 SHIFT = 3。
所以我把 sample 重新計算為:
`Hello, NPU!` 會輸出 `Lipps, RTY!`,
`abc XYZ` 會輸出 `efg BCD`。
我也確認 edge case:`wxyz WXYZ` 應輸出 `abcd ABCD`。
我先執行 unittest 確認紅燈,再建立 `main.py`,最後重新執行 unittest 確認綠燈。
21 changes: 21 additions & 0 deletions weeks/week-18/solutions/1114405013/p2_caesar_cipher/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import sys


SHIFT = 4


def shift_char(char):
if "a" <= char <= "z":
return chr((ord(char) - ord("a") + SHIFT) % 26 + ord("a"))
if "A" <= char <= "Z":
return chr((ord(char) - ord("A") + SHIFT) % 26 + ord("A"))
return char


def main():
text = sys.stdin.read()
sys.stdout.write("".join(shift_char(char) for char in text))


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import subprocess
import sys
import unittest


class TestCaesarCipherProgram(unittest.TestCase):
def run_program(self, input_text):
result = subprocess.run(
[sys.executable, "main.py"],
input=input_text,
text=True,
capture_output=True,
)
self.assertEqual(
result.returncode,
0,
msg=f"程式應正常結束,但 stderr 是:{result.stderr}",
)
return result.stdout

def test_sample_case_shifts_uppercase_and_lowercase_letters(self):
input_text = "Hello, NPU!\nabc XYZ\n"
expected = "Lipps, RTY!\nefg BCD\n"
self.assertEqual(self.run_program(input_text), expected)

def test_edge_case_wraps_around_z_and_Z(self):
input_text = "wxyz WXYZ zZ aA\n"
expected = "abcd ABCD dD eE\n"
self.assertEqual(self.run_program(input_text), expected)

def test_special_case_keeps_non_letters_and_blank_lines(self):
input_text = "123, !?\n\nTaiwan 2026!\n"
expected = "123, !?\n\nXemaer 2026!\n"
self.assertEqual(self.run_program(input_text), expected)


if __name__ == "__main__":
unittest.main()
84 changes: 84 additions & 0 deletions weeks/week-18/solutions/1114405013/p3_digit_root_base/AI_LOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# AI_LOG

## 開工前資訊檢查表

### ① 函式簽名

本題不是只寫函式,而是整支程式讀 stdin、印 stdout。
主要程式檔為 `main.py`。
程式從標準輸入讀入多行非負整數,對每一行輸出一行結果。

### ② 輸入邊界

輸入可能有多行,每行是一個非負整數,讀到 EOF 結束。
可能出現 0。
每個輸入數字都要各自處理,並且每個輸入對應一行輸出。
我的學號參數為 base = 3。

### ③ 例外處理

題目主要處理合法的非負整數輸入。
如果輸入為空,程式不輸出任何內容。
每行輸入會先去除換行與空白後再處理。
不額外擴充題目沒有要求的非法格式處理。

### ④ edge case

我測試 `0`,因為 0 是最小非負整數,而且它本身就是一位數。
預期輸出是 `0`。

我也測試 `63`,因為它需要多輪計算:
63 的 base 3 是 2100,2+1+0+0=3;
3 的 base 3 是 10,1+0=1;
所以最後輸出 1。

### ⑤ 驗收標準

base 固定為 3。
每個輸入數字都要轉成 base 3 後進行位數相加。
如果結果仍不是一位數,就重複流程直到得到一位數。
每個輸入對應一行輸出。
輸出必須和 expected output 完全一致,包含換行。
我會用 `python -m unittest -v test_digit_root_base.py` 驗證。
測試必須先紅燈,再完成 `main.py` 實作後變綠燈。

---

# AI 使用紀錄:第三題 任意進位的數字根

## 我問了 AI 什麼

1. 我請 AI 根據第三題「任意進位的數字根」題目,先設計 unittest 測試。
2. 我告訴 AI 這題是整支程式讀 stdin、印 stdout,不是只寫函式。
3. 我提供題目規格:
- base 固定為 3
- stdin 可能有多行非負整數
- 讀到 EOF 結束
- 每個數字要先轉成 base 3
- 將 base 3 的各位數相加
- 若結果還不是一位數,要繼續重複處理
4. 我要求 AI 先只建立測試檔 `test_digit_root_base.py`,不要建立 `main.py`。
5. 我確認 red test 失敗,原因是還沒有 `main.py`。
6. 我完成 `test:` commit 後,請 AI 幫我建立 `main.py` 讓測試通過。

## AI 給了我什麼

1. AI 幫我建立 unittest 測試檔:

```text
test_digit_root_base.py
2. AI 設計了 3 個 stdin/stdout 測試案例:

sample 一般案例:輸入 0、8、63,預期輸出 0、2、1
edge case:輸入 0,預期輸出 0
多輪相加案例:輸入 63,預期輸出 1

## 我改了什麼

我先執行 unittest,確認因為沒有 main.py,所以測試是 red test。

我完成 test: commit。

我請 AI 建立 main.py,實作 base 3 數字根。

我再次執行 unittest,確認測試全部通過。
Loading