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
61 changes: 61 additions & 0 deletions weeks/week-02/solutions/1112405053/1one.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

import sys
import re
import random


def generate_numbers(y: int):
"""Generate a deterministic sequence of y numbers.

The sequence uses y as the random seed so the same input always
produces the same output, which keeps the result reproducible.
"""
rng = random.Random(y)
upper_bound = max(10, y * 2)
return [rng.randint(1, upper_bound) for _ in range(y)]


def process_input(text: str):
text = text.strip()
if not text:
return None
try:
y = int(text)
except ValueError:
print("請輸入整數")
return None
if y <= 0:
print("請輸入正整數")
return None

nums = generate_numbers(y)
print(f"目前數列:{' '.join(map(str, nums))}")

# remove duplicates while keeping original order
seen = set()
unique = []
for n in nums:
if n not in seen:
seen.add(n)
unique.append(n)

# keep numbers divisible by 5 and sort ascending
result = sorted(n for n in unique if n % 5 == 0)
return result


def main():
data = sys.stdin.read()
if not data:
return
res = process_input(data)
if res is None:
return
if res:
print(' '.join(map(str, res)))
else:
print("NONE")


if __name__ == '__main__':
main()
32 changes: 32 additions & 0 deletions weeks/week-02/solutions/1112405053/2two.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import sys


def shift_letters(text: str, shift: int = 4) -> str:
"""Shift all English letters by 4 positions (Caesar cipher).
Z shifts to D, a shifts to e, etc. Non-letter characters remain unchanged."""
result = []
for char in text:
if 'A' <= char <= 'Z':
# Uppercase letters
new_char = chr((ord(char) - ord('A') + shift) % 26 + ord('A'))
result.append(new_char)
elif 'a' <= char <= 'z':
# Lowercase letters
new_char = chr((ord(char) - ord('a') + shift) % 26 + ord('a'))
result.append(new_char)
else:
# Non-letter characters remain unchanged
result.append(char)
return ''.join(result)


def main():
data = sys.stdin.read()
if not data:
return
result = shift_letters(data.rstrip('\n'))
print(result)


if __name__ == '__main__':
main()
110 changes: 110 additions & 0 deletions weeks/week-02/solutions/1112405053/3three.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import sys

def to_base3(n: int) -> str:
if n == 0:
return '0'
digits = []
while n > 0:
digits.append(str(n % 3))
n //= 3
return ''.join(reversed(digits))


def iterative_base3_digit_sum_steps(n: int):
"""Return a list of step strings and the final single-digit result.

Each step string has the form: "N -> base3 -> sum: S".
"""
steps = []
current = n
# handle zero explicitly
if current == 0:
steps.append("0 -> 0 -> sum: 0")
return steps, 0
b3 = to_base3(current)
current = sum(int(d) for d in b3)
steps.append(f"{n} -> {b3} -> sum: {current}")

while current >= 10:
digits_sum = sum(int(d) for d in str(current))
steps.append(f"{current} -> sum: {digits_sum}")
current = digits_sum
return steps, current


def run_cli(data: str):
data = data.strip()
if not data:
return
try:
n = int(data)
except ValueError:
print("請輸入整數")
return
steps, result = iterative_base3_digit_sum_steps(n)
for s in steps:
print(s)
print(f"最終結果:{result}")


def run_gui():
try:
import tkinter as tk
from tkinter import messagebox
except Exception:
print("無法載入 Tkinter,請使用命令列模式")
return

def on_compute(event=None):
txt_output.delete('1.0', tk.END)
raw = entry.get().strip()
if raw == '':
return
try:
n = int(raw)
except ValueError:
messagebox.showerror('錯誤', '請輸入整數')
return
steps, result = iterative_base3_digit_sum_steps(n)
for s in steps:
txt_output.insert(tk.END, s + '\n')
txt_output.insert(tk.END, f"最終結果:{result}\n")

root = tk.Tk()
root.title('Base-3 迭代加總')

frm = tk.Frame(root, padx=8, pady=8)
frm.pack(fill=tk.BOTH, expand=True)

lbl = tk.Label(frm, text='輸入十進位整數:')
lbl.grid(row=0, column=0, sticky='w')

entry = tk.Entry(frm, width=30)
entry.grid(row=0, column=1, sticky='we')
entry.bind('<Return>', on_compute)

btn = tk.Button(frm, text='計算 (Enter)', command=on_compute)
btn.grid(row=0, column=2, padx=6)

txt_output = tk.Text(frm, height=10, width=60)
txt_output.grid(row=1, column=0, columnspan=3, pady=8)

# make columns expand
frm.columnconfigure(1, weight=1)

entry.focus()
root.mainloop()


def main():
# If there's piped input, run CLI mode. Otherwise open GUI (pressing F5 in an editor
# typically runs the script directly and will show the GUI window).
if not sys.stdin.isatty():
data = sys.stdin.read()
run_cli(data)
else:
run_gui()


if __name__ == '__main__':
main()
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions weeks/week-02/solutions/1112405053/4four/plot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np

# 維度定義
labels = [
'Speed for Large N\n(大N速度)',
'Speed for Small N\n(小N速度)',
'No Sorting Required\n(免預先排序)',
'Implementation Simplicity\n(實作簡易度)',
'Worst-case Cmps\n(最壞比較次數)'
]
num_vars = len(labels)

# 線性搜尋與二分搜尋的歸一化得分 (0~1)
# 數值設計呼應 README 中的多維權衡邏輯
linear_scores = [0.1, 1.0, 1.0, 1.0, 0.1]
binary_scores = [1.0, 0.8, 0.2, 0.6, 1.0]

# 雷達圖需要首尾相連
angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
linear_scores += linear_scores[:1]
binary_scores += binary_scores[:1]
angles += angles[:1]

fig, ax = plt.subplots(figsize=(7, 7), subplot_kw=dict(polar=True))

# 畫出極座標網格與標籤
plt.xticks(angles[:-1], labels, color='grey', size=10)

# 設定 y 軸範圍與刻度
ax.set_rlabel_position(0)
plt.yticks([0.2, 0.4, 0.6, 0.8, 1.0], ["0.2", "0.4", "0.6", "0.8", "1.0"], color="grey", size=8)
plt.ylim(0, 1.1)

# 繪製線性搜尋
ax.plot(angles, linear_scores, linewidth=2, linestyle='solid', label='Linear Search (線性搜尋)', color='#e74c3c')
ax.fill(angles, linear_scores, color='#e74c3c', alpha=0.25)

# 繪製二分搜尋
ax.plot(angles, binary_scores, linewidth=2, linestyle='solid', label='Binary Search (二分搜尋)', color='#3498db')
ax.fill(angles, binary_scores, color='#3498db', alpha=0.25)

# 新增標題與圖例
plt.title('Multi-Dimensional Trade-off: Linear vs. Binary Search\n(線性 vs 二分搜尋多維權衡雷達圖)', size=14, y=1.1, fontweight='bold')
plt.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1))

# 儲存圖片
plt.tight_layout()
plt.savefig('assets/radar.png', dpi=300)
print("Radar chart generated successfully at assets/radar.png")
82 changes: 82 additions & 0 deletions weeks/week-02/solutions/1112405053/4four/search_eval.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import timeit
import random
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np

# 1. 產生升冪排序的整數陣列
N = 100000
# 為了確保能找到, 讓數值範圍涵蓋 153 並且有足夠的大小差距
# 我們建立一個包含 0 到 200000 之間的奇數或特定間隔,
# 這裡簡單用範圍整數確保 153 必定在其中
arr = list(range(0, N * 2, 2)) # 產生偶數陣列
# 強制把 153 放進去,或者我們直接用連續整數確保存在與位置隨機
arr = list(range(1, N + 1))

target = 153 # K = 100 + 53

# 2. 實作二分搜尋(計算比較次數)
def binary_search(array, k):
low = 0
high = len(array) - 1
cmp_count = 0

while low <= high:
cmp_count += 1
mid = (low + high) // 2
if array[mid] == k:
return mid, cmp_count
elif array[mid] < k:
low = mid + 1
else:
high = mid - 1
return -1, cmp_count

# 為了比對,也寫一個簡單的線性搜尋計算比較次數
def linear_search_cmp(array, k):
cmp_count = 0
for i in range(len(array)):
cmp_count += 1
if array[i] == k:
return i, cmp_count
return -1, cmp_count

# 執行搜尋並輸出結果
idx, cmp_bin = binary_search(arr, target)
if idx != -1:
print(f"FOUND {idx} cmp={cmp_bin}")
else:
print(f"NOT FOUND cmp={cmp_bin}")

# 3. 用 timeit 量測效能
# 為了避免線性搜尋在前面太快找到,我們用完整跑完或多次量測的平均
# linear_search 的原生實作供 timeit 使用
def run_linear():
for x in arr:
if x == target:
break

def run_binary():
low = 0
high = len(arr) - 1
while low <= high:
mid = (low + high) // 2
if arr[mid] == target:
break
elif arr[mid] < target:
low = mid + 1
else:
high = mid - 1

# 由於二分搜尋極快,我們讓它執行較多次數以利量測
t_linear = timeit.timeit(run_linear, number=100)
t_binary = timeit.timeit(run_binary, number=100)

print(f"linear: {t_linear:.6f} s")
print(f"binary: {t_binary:.6f} s")

if t_binary < t_linear:
print("binary faster")
else:
print("linear faster")
Loading