From 17f0b018ef1714dc6fc50dc2b4b91a17d56bfa9b Mon Sep 17 00:00:00 2001 From: yuchi-create Date: Mon, 22 Jun 2026 20:44:29 +0800 Subject: [PATCH 1/4] Add failing tests for digital root in arbitrary base (week18 Q3, red light) digital_root module does not exist yet; test_log_red.txt records the collection error confirming the tests fail before implementation. Co-Authored-By: Claude Sonnet 4.6 --- .../solutions/1114405055/test_digital_root.py | 74 +++++++++++++++++++ .../solutions/1114405055/test_log_red.txt | 22 ++++++ 2 files changed, 96 insertions(+) create mode 100644 weeks/week-18/solutions/1114405055/test_digital_root.py create mode 100644 weeks/week-18/solutions/1114405055/test_log_red.txt diff --git a/weeks/week-18/solutions/1114405055/test_digital_root.py b/weeks/week-18/solutions/1114405055/test_digital_root.py new file mode 100644 index 000000000..b8cee1d1d --- /dev/null +++ b/weeks/week-18/solutions/1114405055/test_digital_root.py @@ -0,0 +1,74 @@ +# 第三題:任意進位的數字根 -- 測試 +# 學號 1114405055 末兩碼 55,個位 u=5,查表得 base=7 +# +# digit_sum_in_base(x, base):x 換算成 base 進位後,把各位數字加總,回傳十進位整數 +# digital_root(x, base):重複呼叫 digit_sum_in_base 直到結果是 base 進位下的一位數 +# x=0 時題目規定直接回傳 0,不套公式硬算 + +import pytest + +from digital_root import digit_sum_in_base, digital_root + +BASE = 7 + + +def test_zero_is_zero_by_definition(): + # 題目明文規定 x=0 的數字根固定是 0,不能用一般迭代公式去算 + assert digital_root(0, BASE) == 0 + + +def test_already_single_digit_no_iteration_needed(): + # x < base 時,本身在 base 進位下就是一位數,不需要任何累加迭代 + for x in range(1, BASE): + assert digital_root(x, BASE) == x + + +def test_sample_8_one_iteration_to_converge(): + # 8 在 7 進位是 11 -> 1+1=2,2 < 7 已是一位數,迭代一次即收斂 + assert digit_sum_in_base(8, BASE) == 2 + assert digital_root(8, BASE) == 2 + + +def test_sample_63_needs_two_iterations_to_converge(): + # 63 在 7 進位是 120 -> 1+2+0=3,3 < 7 已是一位數 + # 這組驗證「相加一次後仍可能不是一位數,需再轉一次進位再加一次」的收斂邊界 + assert digit_sum_in_base(63, BASE) == 3 + assert digital_root(63, BASE) == 3 + + +def test_needs_multiple_rounds_to_converge_to_single_digit(): + # 自行驗算:x=1000000 在 7 進位是 11333311 + # 第一輪:1+1+3+3+3+3+1+1 = 16,16 在 7 進位是 22(兩位數,尚未收斂) + # 第二輪:2+2 = 4,4 < 7 已是一位數 + # 證明 digital_root 必須是「迴圈直到一位數」而非只做固定一次相加 + x = 1_000_000 + first_round = digit_sum_in_base(x, BASE) + assert first_round == 16 + assert first_round >= BASE # 第一次相加後仍是兩位數,尚未收斂 + second_round = digit_sum_in_base(first_round, BASE) + assert second_round == 4 + assert digital_root(x, BASE) == 4 + + +def test_large_value_terminates_quickly(): + # x 接近上限 1e9,確認迴圈會收斂且不會死迴圈或效能爆炸 + x = 10**9 + result = digital_root(x, BASE) + assert 0 <= result < BASE + + +@pytest.mark.parametrize("x", [0, 1, 6, 7, 8, 63, 1_000_000, 10**9]) +def test_digital_root_always_single_digit_in_base(x): + # 數字根定義上必須落在 [0, base) 之間(在 base 進位下是一位數) + assert 0 <= digital_root(x, BASE) < BASE + + +def test_base_16_conversion_not_hardcoded_for_small_base(): + # 題目特別提醒 base 可能是 16,確認進位轉換/輸出邏輯沒有寫死成只服務小 base + # 255 在 16 進位是 FF -> 十進位數字相加 15+15=30,30 在 16 進位是 1E -> 1+14=15 + base16 = 16 + assert digit_sum_in_base(255, base16) == 30 + assert digital_root(255, base16) == 15 + # 16 進位下剛好一位數的情況 + assert digital_root(15, base16) == 15 + assert digital_root(0, base16) == 0 diff --git a/weeks/week-18/solutions/1114405055/test_log_red.txt b/weeks/week-18/solutions/1114405055/test_log_red.txt new file mode 100644 index 000000000..28ade1cc3 --- /dev/null +++ b/weeks/week-18/solutions/1114405055/test_log_red.txt @@ -0,0 +1,22 @@ +============================= test session starts ============================= +platform win32 -- Python 3.13.9, pytest-8.4.2, pluggy-1.5.0 -- C:\Users\User\anaconda3\python.exe +cachedir: .pytest_cache +rootdir: C:\Users\User\Desktop\0622-3\2026-python\weeks\week-18\solutions\1114405055 +plugins: anyio-4.10.0 +collecting ... collected 0 items / 1 error + +=================================== ERRORS ==================================== +____________________ ERROR collecting test_digital_root.py ____________________ +ImportError while importing test module 'C:\Users\User\Desktop\0622-3\2026-python\weeks\week-18\solutions\1114405055\test_digital_root.py'. +Hint: make sure your test modules/packages have valid Python names. +Traceback: +C:\Users\User\anaconda3\Lib\importlib\__init__.py:88: in import_module + return _bootstrap._gcd_import(name[level:], package, level) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +test_digital_root.py:10: in + from digital_root import digit_sum_in_base, digital_root +E ModuleNotFoundError: No module named 'digital_root' +=========================== short test summary info =========================== +ERROR test_digital_root.py +!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!! +============================== 1 error in 0.08s =============================== From 89a7d9129f9d9acdbdea236cd9853aac2e971224 Mon Sep 17 00:00:00 2001 From: yuchi-create Date: Mon, 22 Jun 2026 20:44:36 +0800 Subject: [PATCH 2/4] Implement digital root in arbitrary base (week18 Q3, green light, base=7) digit_sum_in_base() converts x into base and sums its digits; digital_root() loops that until a single digit, with x=0 fixed to 0 per spec. test_log_green.txt records all 15 tests passing. Co-Authored-By: Claude Sonnet 4.6 --- .../solutions/1114405055/digital_root.py | 37 +++++++++++++++++++ .../solutions/1114405055/test_log_green.txt | 24 ++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 weeks/week-18/solutions/1114405055/digital_root.py create mode 100644 weeks/week-18/solutions/1114405055/test_log_green.txt diff --git a/weeks/week-18/solutions/1114405055/digital_root.py b/weeks/week-18/solutions/1114405055/digital_root.py new file mode 100644 index 000000000..015ea9f06 --- /dev/null +++ b/weeks/week-18/solutions/1114405055/digital_root.py @@ -0,0 +1,37 @@ +# 第三題:任意進位的數字根 +# 學號 1114405055 末兩碼 55,個位 u=5,查表得 base=7 + +BASE = 7 + + +def digit_sum_in_base(x: int, base: int) -> int: + """把 x 換算成 base 進位,將各位數字相加,回傳十進位整數。""" + total = 0 + while x > 0: + total += x % base + x //= base + return total + + +def digital_root(x: int, base: int) -> int: + """重複對 base 進位下的各位數字相加,直到結果是一位數(< base)。""" + if x == 0: + return 0 + while x >= base: + x = digit_sum_in_base(x, base) + return x + + +def main() -> None: + import sys + + for line in sys.stdin: + line = line.strip() + if not line: + continue + x = int(line) + print(digital_root(x, BASE)) + + +if __name__ == "__main__": + main() diff --git a/weeks/week-18/solutions/1114405055/test_log_green.txt b/weeks/week-18/solutions/1114405055/test_log_green.txt new file mode 100644 index 000000000..dfde15351 --- /dev/null +++ b/weeks/week-18/solutions/1114405055/test_log_green.txt @@ -0,0 +1,24 @@ +============================= test session starts ============================= +platform win32 -- Python 3.13.9, pytest-8.4.2, pluggy-1.5.0 -- C:\Users\User\anaconda3\python.exe +cachedir: .pytest_cache +rootdir: C:\Users\User\Desktop\0622-3\2026-python\weeks\week-18\solutions\1114405055 +plugins: anyio-4.10.0 +collecting ... collected 15 items + +test_digital_root.py::test_zero_is_zero_by_definition PASSED [ 6%] +test_digital_root.py::test_already_single_digit_no_iteration_needed PASSED [ 13%] +test_digital_root.py::test_sample_8_one_iteration_to_converge PASSED [ 20%] +test_digital_root.py::test_sample_63_needs_two_iterations_to_converge PASSED [ 26%] +test_digital_root.py::test_needs_multiple_rounds_to_converge_to_single_digit PASSED [ 33%] +test_digital_root.py::test_large_value_terminates_quickly PASSED [ 40%] +test_digital_root.py::test_digital_root_always_single_digit_in_base[0] PASSED [ 46%] +test_digital_root.py::test_digital_root_always_single_digit_in_base[1] PASSED [ 53%] +test_digital_root.py::test_digital_root_always_single_digit_in_base[6] PASSED [ 60%] +test_digital_root.py::test_digital_root_always_single_digit_in_base[7] PASSED [ 66%] +test_digital_root.py::test_digital_root_always_single_digit_in_base[8] PASSED [ 73%] +test_digital_root.py::test_digital_root_always_single_digit_in_base[63] PASSED [ 80%] +test_digital_root.py::test_digital_root_always_single_digit_in_base[1000000] PASSED [ 86%] +test_digital_root.py::test_digital_root_always_single_digit_in_base[1000000000] PASSED [ 93%] +test_digital_root.py::test_base_16_conversion_not_hardcoded_for_small_base PASSED [100%] + +============================= 15 passed in 0.02s ============================== From e2141c63b58cc5bba9c9a9d28b9ec77fefef4416 Mon Sep 17 00:00:00 2001 From: yuchi-create Date: Mon, 22 Jun 2026 20:47:18 +0800 Subject: [PATCH 3/4] Add AI collaboration log for week18 Q3 digital root task Co-Authored-By: Claude Sonnet 4.6 --- weeks/week-18/solutions/1114405055/ai_log.md | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 weeks/week-18/solutions/1114405055/ai_log.md diff --git a/weeks/week-18/solutions/1114405055/ai_log.md b/weeks/week-18/solutions/1114405055/ai_log.md new file mode 100644 index 000000000..c3c6b0717 --- /dev/null +++ b/weeks/week-18/solutions/1114405055/ai_log.md @@ -0,0 +1,24 @@ +# AI 協作紀錄 — 第三題:任意進位的數字根 + +## 需求確認 +- 學號 1114405055 末兩碼 55 → 個位 u=5 → 查表 base=7(依使用者明確指定,不可混用其他題目的終止邏輯) +- 輸入:每行一個十進位非負整數 x,讀到 EOF 結束(與第二題相同,但不同於第一題的 n=0 終止) +- x=0 的數字根規定為 0,不能套一般迭代公式硬算 + +## 設計決策(先問後做) +- **base 是否做成命令列/環境變數參數?** 已詢問使用者,選擇直接寫死 `BASE = 7` 常數,理由是題目已用學號決定 base,做成可帶參數屬於題目未要求的額外設計(違反「最小化、不過度設計」原則)。 +- **函式拆兩個(digit_sum_in_base / digital_root)而非合成一個?** + 因為測試需要分別驗證「兩位數但只迭代一次就收斂」與「需要兩輪才收斂」這兩種邊界情境,若合成一個函式無法在測試中檢查中間結果,故拆開。 + +## 開發流程(TDD:紅燈 → 綠燈) +1. 先寫 `test_digital_root.py`,涵蓋使用者列出的所有 edge case(x=0、x Date: Mon, 22 Jun 2026 20:50:29 +0800 Subject: [PATCH 4/4] Rename Q3 artifacts with question prefix to make room for other questions Co-Authored-By: Claude Sonnet 4.6 --- .../1114405055/{ai_log.md => ai_log_q3_digital_root.md} | 8 ++++---- .../{test_log_green.txt => test_log_q3_green.txt} | 0 .../1114405055/{test_log_red.txt => test_log_q3_red.txt} | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename weeks/week-18/solutions/1114405055/{ai_log.md => ai_log_q3_digital_root.md} (88%) rename weeks/week-18/solutions/1114405055/{test_log_green.txt => test_log_q3_green.txt} (100%) rename weeks/week-18/solutions/1114405055/{test_log_red.txt => test_log_q3_red.txt} (100%) diff --git a/weeks/week-18/solutions/1114405055/ai_log.md b/weeks/week-18/solutions/1114405055/ai_log_q3_digital_root.md similarity index 88% rename from weeks/week-18/solutions/1114405055/ai_log.md rename to weeks/week-18/solutions/1114405055/ai_log_q3_digital_root.md index c3c6b0717..cc3920037 100644 --- a/weeks/week-18/solutions/1114405055/ai_log.md +++ b/weeks/week-18/solutions/1114405055/ai_log_q3_digital_root.md @@ -12,13 +12,13 @@ ## 開發流程(TDD:紅燈 → 綠燈) 1. 先寫 `test_digital_root.py`,涵蓋使用者列出的所有 edge case(x=0、x