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
100 changes: 100 additions & 0 deletions weeks/week-18/solutions/1114405056/A_datacleaning/AI_LOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# AI_LOG

目的:記錄本次與 AI 的互動要點,含使用者提問、AI 回應與使用者要求更正的項目。

- 時間範圍:2026-06-22(對話摘要)
- 主要任務:實作「資料清理」題目(D=4),並在指定資料夾建立實作與測試;測試中保留一個故意失敗項目(紅燈)。

## 1) 使用者問了什麼

- 要把實作與測試放到 `D:\1114405056-0622\2026-python\weeks\week-18\solutions\1114405056\A_datacleaning`
- 希望測試(紅燈)與實作(綠燈)並存(即一個故意失敗的測試)
- 要求使用去重保序邏輯
- 要求 D = 4
- 提供 Sample Input 要求算出輸出
- 要求把測試與實作正確分離(test_solution.py / solution.py)
- 要求產出本次 AI_LOG.md 記錄

## 2) AI 給了什麼

- 提供了可通過的實作 solution.py(D=4,使用 dedupe())
- 提供了測試檔 test_solution.py,包含 1 個故意失敗的測試(test_intentional_fail)與數個正確測試
- 提供了執行測試與檢視輸出的指令範例
- 回答 Sample Input(第一組輸出為 4,第二組輸出為 NONE)
- 提供了 README.md 和本 AI_LOG.md 文件

## 3) 使用者要求更正或追蹤的地方

- 無(首次創建)

## 4) 目前資料夾內重要檔案(建議檢查)

- solution.py (實作,D=4,使用 dedupe)
- test_solution.py (測試,含故意失敗項 test_intentional_fail)
- README.md (說明文件)
- AI_LOG.md (本文件)

# 程式介面(函式說明)

## dedupe(items)

- 參數:items — 可迭代的整數序列 (iterable[int])
- 回傳:產生器 (generator[int]),依序產出第一次出現的項目(保序去重)

## main()

- 參數:無(從標準輸入讀取)
- 回傳:無(將結果列印到標準輸出)
- 行為:讀取多組測資(每組以整數 n 開頭,若 n == 0 則結束),每組讀取 n 個整數並輸出處理結果

## 資料範圍與複雜度

- n 範圍:1 ≤ n ≤ 10^5(每組);多組輸入總和可能更大
- 整數範圍:-10^9 < a_i < 10^9
- 演算法複雜度:O(n + k log k) 每組(n 為該組長度,k 為保留的元素數量);空間 O(n)(用於 seen 集合)

## 輸入方式與終止條件

- 格式:多組測資,每組先一個整數 n,接著 n 個以空白分隔的整數;遇到 n == 0 則結束(該組不處理)
- 讀取行為:程式以一次性 token 讀入(stdin),不是逐行固定行數;亦可視為讀到 EOF 或遇到 0 為止

## 非法輸入 / 格式錯誤處理

- 本實作假設輸入均為符合格式的整數序列(與競賽型題目常態一致)
- 若出現非整數 token 或數量不足,程式會在轉換為 int 時拋出例外(ValueError 或 IndexError),目前未捕捉;建議測試階段提供合法輸入
- 如需健壯處理,可在 main 加上例外捕捉並以錯誤訊息或退出碼處理(未在目前實作中加入)

## 輸入邊界、例外與 edge case(至少一項)

邊界案例:

1. n = 0(代表結束,整個程式不輸出該組)
2. 所有數字都被剔除(去重後或篩選後無符合者)→ 輸出 "NONE"
3. 剛好一個元素且等於門檻的倍數(例如單一數字可被 D 整除)→ 輸出該數
4. 所有元素相同(重複多次)且可被 D 整除 → 只保留一次並輸出
5. 負數或 0(0 被任何 D 整除,應視為可保留)

## 例子(edge case 範例)

- 輸入:1 0 0 → 輸出:0 (n=1,數值 0;0 % D == 0)
- 輸入:3 4 4 4 0 → 輸出:4 (重複但只保留第一次)
- 輸入:2 1 3 0 → 輸出:NONE

## 驗收標準(何謂正確輸出)

每組輸出應滿足:

1. 先對原序列做「保序去重」(保留第一次出現)
2. 再只保留能被 D 整除的數(D 為整數常數)
3. 最後把保留元素由小到大排序並以單一空白分隔輸出;若無任何元素,輸出 "NONE"

範例驗收(依本次設定的 D):

- 使用者指定/本實作設定:D = 4
- 以 Sample Input:
- 第1組 (8 4 7 4 2 9 2 6 7) → 去重保序後 [4,7,2,9,6] → 篩選後只有 4 → 輸出 "4"
- 第2組 (3 1 3 5) → 無符合 → 輸出 "NONE"

## 本次使用的 D 參數

- D = 4(已寫入 solution.py)
108 changes: 108 additions & 0 deletions weeks/week-18/solutions/1114405056/A_datacleaning/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Week 18(115/06/22-115/06/28)

- 主題:期末考
- 解題:本週無 `QUESTION-*.md`
- 作業:完成期末作業提交與學期回顧

---

## 本週建議

- 依教師公告完成期末考核項目
- 在 `weeks/week-18/solutions/<student-id>/README.md` 提交學期總結


---

## AI 使用方式

1. 讀 {問題說明} 設計一版針對該問題的 python unit-test 程式,並加上繁體中文的註解放到 {指定目錄} 中
2. 幫我寫一版 python 程式,並跑完測試,並保留測試紀錄
3. 幫我加上繁體中文的註解說明
4. 有更簡單、更容易記憶的方式來寫這個程式,在檔名後加上 `-easy`
5. 幫我加上繁體中文的詳細註解說明

## 今天任務

因為 CPE 是要當場打程式設計出來,所以請手動把簡單版本程式在 `week-#/solutions/{學號}` 中打一遍你的程式,並進行測試。

以下是送出標準
- 參考 [GITHUB_WORKFLOW](GITHUB_WORKFLOW.md) 將程式 PR 出來
- 內容 (2 程式、1 測試 及 LOG 資料)要包括:
- AI 教你的簡單版本,有中文註解
- 你手打的程式
- 測試程式
- 你手打程式的測試 LOG 記錄

## 第 1 題:資料清理

### 題目說明

學號末兩碼為 56,
個位數 `u = 6`,
所以 `D = 4`(整除常數)。

本題需要進行以下操作:

1. **保序去重**:保留第一次出現的元素
2. **篩選**:只保留能被 D 整除的數
3. **排序**:由小到大排序
4. **輸出**:以單一空白分隔,或輸出 "NONE"

### 演算法說明

程式逐組讀取輸入,每組先讀一個整數 n,再讀 n 個整數。

對每組執行:
1. 使用 `dedupe()` 函式進行保序去重
2. 篩選出能被 D(即 4)整除的數
3. 排序
4. 輸出結果或 "NONE"

### 時間複雜度

- n 範圍:1 ≤ n ≤ 10^5(每組)
- 演算法複雜度:O(n + k log k)(n 為該組長度,k 為保留的元素數量)
- 空間複雜度:O(n)(用於 seen 集合)

### 輸入輸出格式

**輸入**:多組測資,每組先一個整數 n,接著 n 個整數;遇到 n == 0 則結束。

**輸出**:每組一行,輸出排序後的結果或 "NONE"。

## 驗收標準

- 輸入 `8 4 7 4 2 9 2 6 7` ➔ 輸出 `4`
- 去重保序:[4, 7, 2, 9, 6]
- 篩選(能被 4 整除):[4]
- 排序:[4]
- 輸出:`4`

- 輸入 `3 1 3 5` ➔ 輸出 `NONE`
- 去重保序:[1, 3, 5]
- 篩選(能被 4 整除):[]
- 輸出:`NONE`

## Edge Case

已檢查:

1. 去重:重複出現的元素只保留第一次
2. 篩選:所有元素都不符合條件時輸出 "NONE"
3. 排序:排序後輸出
4. 多組輸入:支援多組輸入直到 0 為止

## 測試方式

在本資料夾執行:

```bash
py -m pytest test_solution.py -v
```

或:

```bash
py test_solution.py
```
58 changes: 58 additions & 0 deletions weeks/week-18/solutions/1114405056/A_datacleaning/solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""第一題:資料清理 (Data Cleaning)

學號末兩碼為 56,個位數 u = 6,
所以 D = 4(整除常數)。

本題需要進行以下操作:
1. 保序去重(保留第一次出現的元素)
2. 篩選能被 D 整除的數
3. 排序並輸出,或輸出 "NONE"
"""

import sys

D = 4 # 整除常數


def dedupe(items):
"""保序去重:產生器,依序產出第一次出現的項目。"""
seen = set()
for item in items:
if item not in seen:
yield item
seen.add(item)


def main():
"""主程式:讀取多組測資並輸出結果。

輸入格式:多組測資,每組先一個整數 n,接著 n 個整數;
遇到 n == 0 則結束。
"""
data = sys.stdin.buffer.read().split()
i = 0
out_lines = []

while i < len(data):
n = int(data[i])
i += 1

if n == 0:
break

# 讀取該組的 n 個整數
group = list(map(int, data[i:i+n]))
i += n

# 保序去重,然後篩選能被 D 整除的數
keep = [x for x in dedupe(group) if x % D == 0]
keep.sort()

# 輸出結果
out_lines.append(" ".join(map(str, keep)) if keep else "NONE")

print("\n".join(out_lines))


if __name__ == "__main__":
main()
38 changes: 38 additions & 0 deletions weeks/week-18/solutions/1114405056/A_datacleaning/test_solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import os
import sys
import subprocess

HERE = os.path.dirname(__file__)
SCRIPT = os.path.join(HERE, "solution.py")


def run_input(inp: str) -> str:
"""執行程式並返回輸出結果。"""
p = subprocess.run(
[sys.executable, SCRIPT],
input=inp,
capture_output=True,
text=True
)
return p.stdout


def test_intentional_fail():
"""故意失敗的測試(紅燈):錯誤期望造成 fail。"""
# 真正輸出為 "4 8\n",這裡錯誤地期望 "8 4\n"
assert run_input("5 8 4 2 4 8 0") == "8 4\n"


def test_single_case():
"""測試:去重、保序、篩除非 4 的倍數、排序。"""
assert run_input("5 8 4 2 4 8 0") == "4 8\n"


def test_none_case():
"""測試:沒有符合條件時輸出 NONE。"""
assert run_input("3 1 3 5 0") == "NONE\n"


def test_multiple_cases():
"""測試:多組輸入。"""
assert run_input("8 4 7 4 2 9 2 6 7 3 1 3 5 0") == "4\nNONE\n"
Loading