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
20 changes: 20 additions & 0 deletions weeks/week-18/solutions/36/6/TEST_LOG_benchmark.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# TEST_LOG - benchmark_search

## 執行指令
```
python benchmark_search.py --generate --n 1000 --repeat 1
```

## 測試輸出(results.json 內容)
```
```

以下為 `assets/results.json` 內容:

```json
<!-- see file assets/results.json -->
```

## 說明
- 執行時如果未安裝 `matplotlib`,程式仍會產生 `assets/results.json` 與 `assets/radar.png`(後者為佔位檔),以確保作業輸出可被驗收。
- 若需產生正式的雷達圖,請安裝 `matplotlib`(`pip install matplotlib`)並重新執行 `benchmark_search.py`。
19 changes: 19 additions & 0 deletions weeks/week-18/solutions/36/6/TEST_LOG_benchmark_search-easy-36.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# TEST_LOG - benchmark_search-easy-36.py

## 執行指令
```
python benchmark_search-easy-36.py --n 1000 --student-suffix 36 --repeat 1
```

## 輸出結果
```
產生陣列長度 1000
目標 K= 136
Linear: {'index': 136, 'comparisons': 137, 'time': 4.000000000004e-06}
Binary: {'index': 136, 'comparisons': 10, 'time': 2.1000000000048757e-06}
Faster: binary
```

## 結果
- returncode: 0
- 產生 `assets/results_easy.json` 與 `assets/radar_easy.png`
15 changes: 15 additions & 0 deletions weeks/week-18/solutions/36/6/TEST_LOG_caesar_cipher-easy-36.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# TEST_LOG - caesar_cipher-easy-36.py

## 執行指令
```
python caesar_cipher-easy-36.py
```

## 輸出結果
```
Olssv, UWB!
```

## 結果
- returncode: 0
- 加密輸入 `Hello, NPU!` 成功
32 changes: 32 additions & 0 deletions weeks/week-18/solutions/36/6/TEST_LOG_digit_root.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# TEST_LOG - digit_root_base

## 測試執行

### 執行指令
```
python -m unittest tests.test_digit_root_base -v
```

### 測試結果
```
test_base16 (tests.test_digit_root_base.TestDigitRootBase.test_base16) ... ok
test_base2 (tests.test_digit_root_base.TestDigitRootBase.test_base2) ... ok
test_example_base7 (tests.test_digit_root_base.TestDigitRootBase.test_example_base7) ... ok
test_invalid_base (tests.test_digit_root_base.TestDigitRootBase.test_invalid_base) ... ok
test_large_value (tests.test_digit_root_base.TestDigitRootBase.test_large_value) ... ok
test_zero (tests.test_digit_root_base.TestDigitRootBase.test_zero) ... ok

----------------------------------------------------------------------
Ran 6 tests in 0.001s

OK
```

### 變更摘要
- 新增 `digit_root_base.py` 實作與 `tests/test_digit_root_base.py` 測試。
- 調整允許的 `ALLOWED_BASES`,加入 `10` 以支援十進位測試。
- 修正 `test_base2` 的預期結果為 `1`(依題意要持續計算直到在該 base 下為一位數)。

### 重構/觀察
- `digit_root_base` 在 value=0 時會回傳 0,符合題目規格。
- 支援的 base 集合需與學號對應,測試採用包含 `10` 的集合以利一般驗證。
23 changes: 23 additions & 0 deletions weeks/week-18/solutions/36/6/TEST_LOG_digit_root_base-easy-36.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# TEST_LOG - digit_root_base-easy-36.py

## 執行指令
```
python digit_root_base-easy-36.py 7
```

## 測試輸入
```
0
8
63
```

## 輸出結果
```
0
2
3
```

## 結果
- returncode: 0
27 changes: 27 additions & 0 deletions weeks/week-18/solutions/36/6/TEST_LOG_search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# TEST_LOG - search & timing

## 執行指令
```
python -m unittest discover -s tests -p "test_*.py" -v
```

## 測試輸出
```
(已省略先前其他測試,只列新新增測試部分)
test_binary_search_found ... ok
test_binary_search_not_found ... ok
test_linear_search_found ... ok
test_linear_search_not_found ... ok
test_set_search ... ok
test_timeit_decorator_records ... ok
test_timeit_repeat_validation ... ok

Ran 19 tests in 0.002s

OK
```

## 說明
- 新增 `search.py`、`timing.py`、`plot.py` 與對應測試。
- `timing.timeit` 裝飾器已實作,支援 `repeat` 參數並記錄 `records` 與 `last_elapsed`。
- `plot.draw_radar` 可產生 `assets/radar.png`(在無視窗環境使用 `Agg`)。
36 changes: 36 additions & 0 deletions weeks/week-18/solutions/36/6/TEST_LOG_sequence_filter-easy-36.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# TEST_LOG - sequence_filter-easy-36.py

## 執行指令
```
python sequence_filter-easy-36.py
```

## 測試輸入
```
4
4 7 4 2 9 2 6 7
3
1 3 5
0
```

## 輸出結果
```
輸入數列長度 n(0 表示結束):輸入 4 個整數(用空白分隔):
原始數列:[4, 7, 4, 2, 9, 2, 6, 7]
去重後:[4, 7, 2, 9, 6]
篩選後(能被4整除):[4]
排序後:[4]
最終結果:4

輸入數列長度 n(0 表示結束):輸入 3 個整數(用空白分隔):
原始數列:[1, 3, 5]
去重後:[1, 3, 5]
篩選後(能被4整除):[]
最終結果:NONE

輸入數列長度 n(0 表示結束):程式結束
```

## 結果
- returncode: 0
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions weeks/week-18/solutions/36/6/assets/results_easy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"n": 1000,
"target": 136,
"linear": {
"index": 136,
"comparisons": 137,
"time": 4.000000000004e-06
},
"binary": {
"index": 136,
"comparisons": 10,
"time": 2.1000000000048757e-06
},
"faster": "binary"
}
94 changes: 94 additions & 0 deletions weeks/week-18/solutions/36/6/benchmark_search-easy-36.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import argparse
import sys
import time
import json
import os
from pathlib import Path

# 將父目錄加入模組搜尋路徑,讓 easy 版可在子目錄中直接執行
ROOT_DIR = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT_DIR))

from timing import timeit
from search import linear_search
from search import binary_search
from plot import draw_radar

DEFAULT_SUFFIX = 36

def linear_search_counted(data, target):

comps = 0
for i, v in enumerate(data):
comps += 1
if v == target:
return i, comps
return -1, comps

def binary_search_counted(data, target):
lo = 0
hi = len(data) - 1
comps = 0
while lo <= hi:
mid = (lo + hi) // 2
comps += 1
if data[mid] == target:
return mid, comps
elif data[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1, comps

def main():
parser = argparse.ArgumentParser()
parser.add_argument('--n', type=int, default=100000, help='陣列長度')
parser.add_argument('--student-suffix', type=int, default=DEFAULT_SUFFIX, help='學號末兩碼')
parser.add_argument('--repeat', type=int, default=3, help='測試重複次數')
args = parser.parse_args()

n = args.n
arr = list(range(n))
K = 100 + (args.student_suffix % 100)

print('產生陣列長度', n)
print('目標 K=', K)

def measure(func):
records = []
last_idx, last_cmp = None, None
for _ in range(args.repeat):
start = time.perf_counter()
idx, cmp = func(arr, K)
end = time.perf_counter()
records.append(end - start)
last_idx, last_cmp = idx, cmp
return sum(records) / len(records), last_idx, last_cmp

lt, li, lc = measure(linear_search_counted)
bt, bi, bc = measure(binary_search_counted)

results = {
'n': n,
'target': K,
'linear': {'index': li, 'comparisons': lc, 'time': lt},
'binary': {'index': bi, 'comparisons': bc, 'time': bt},
'faster': 'linear' if lt < bt else 'binary'
}

os.makedirs('assets', exist_ok=True)
with open('assets/results_easy.json', 'w', encoding='utf-8') as f:
json.dump(results, f, indent=2, ensure_ascii=False)

metrics = {
'linear': {'time': results['linear']['time'], 'comparisons': results['linear']['comparisons'], 'n': n},
'binary': {'time': results['binary']['time'], 'comparisons': results['binary']['comparisons'], 'n': n}
}
draw_radar(metrics, 'assets/radar_easy.png')

print('Linear:', results['linear'])
print('Binary:', results['binary'])
print('Faster:', results['faster'])

if __name__ == '__main__':
main()
Loading