# 112上學期資訊課實作
## 一、基礎程式
### 1. 輸出「南光高中」
```python
# 使用內建函式print
print("南光高中")
```
```python
# 使用標準函式庫中的 sys.stdout
# print底層就是用sys.stdout實作的
# sys.stdout大量輸出時會比print快很多 但這個例子裡差不了多少
from sys import stdout
stdout.write("南光高中\n")
```
### 2. 輸入、輸出2個整數
```python
# 雖然輸入數字 但最後print的時候還是會轉成文字 乾脆不轉了直接輸出
print("第一個數字: " + input())
print("第二個數字: " + input())
```
### 3. 五則運算
```python
# 使用eval函式 簡潔又漂亮
# 輸入使用標準函式庫中的 sys.stdin 比input快太多 當然在這個例子裡也是差不了多少
from sys import stdin
# 將運算子存成一個串列 python中 /是一般除法 //是整數除法(無條件捨去)
ope = ["+", "-", "*", "//", "%"]
# 兩行各一個數字 因為等等要用eval所以不用轉成數字
a, b = stdin.read().split("\n")
for o in ope:
# print等號前的算式時 //要輸出成/ 所以就用o[0]
print(a + o[0] + b + "=" + str(eval(a + o + b)))
```
```python
# 一行解 用列表推導式遍歷ope
(lambda a, b: [print(a + o[0] + b + "=" + str(eval(a + o + b))) for o in ["+", "-", "*", "//", "%"]])(*[input() for _ in range(2)])
```
### 4. 分數及格判斷
```python
# 一般寫法 冗
score = input()
if int(score) >= 60:
print("您的成績為" + score + "分,成績及格")
else:
print("您的成績為" + score + "分,成績不及格")
```
```python
# 一行解 這邊用True = 1, False = 0 將判斷式當作list的index輸出
print((lambda score: "您的成績為" + score + "分," +
["成績不及格", "成績及格"][int(score) >= 60])(input()))
```
```python
# 也可以用三元運算子 可讀性較高
print((lambda score: "您的成績為" + score + "分," +
("成績及格" if int(score) >= 60 else "成績不及格"))(input()))
```
### 5. 重複結構for 2+4+6+...+N
```python
# 老師想要我們這麼寫
n = int(input())
ans = 0
for i in range(2, n+1, 2): # n+1如果寫成n的話 i=n的回合不會執行
ans += i
print(ans)
```
```python
# 也可以用sum代替for 雖然時間複雜度還是O(n)
# 但因為python的內建函數是用cpython實作的 所以會比較快
n = int(input())
print(sum(range(2, n+1, 2)))
```
```python
# 當然 代公式還是最快 時間O(1)
print((lambda x: (x + 1) * x)(int(input()) // 2))
```
### 6. 重複結構while 輸出n n-1 n-2...1
```python
# 老師想要我們這麼寫
n = int(input())
while n: # n==0 時 n作為bool是False 該回合不執行
print(n, end=" ")
n -= 1
```
```python
# 當然 內建函式還是比較快 用列表推導式把range的int轉成str 再join起來輸出
print(" ".join([str(i) for i in range(int(input()), 0, -1)]))
```
### 7. 重複結構while 將n n-2 n-4... 等正整數寫進串列a再輸出 (把空間O(1)的題目硬是改成O(n))
```python
# 老師想要我們這麼寫
n = int(input())
a = [] # python dynamic array 不用分配空間:)
while n >= 0:
a.append(n)
n -= 2
print(" ".join([str(i) for i in a]))
```
```python
# 當然 a完全是多餘的
print(" ".join([str(i) for i in range(int(input()), 0, -2)]))
```
## 二、進階程式
### 1. 將串列進行氣泡排序 - 加碼幾個其他的排序法
```python
# 氣泡排序 Time: O(n²), Space: O(1)
# 每一輪把最大的交換到最後面
lst = [int(i) for i in input().split()]
for i in range(len(lst), 1, -1): # 處理前i個
flag = True # 用flag紀錄 如果整輪都沒有交換就是已經排序好了 可以直接跳出
for j in range(i-1):
if lst[j] > lst[j+1]: # 前面比後面大就交換
lst[j], lst[j+1] = lst[j+1], lst[j] # python交換是交換位址 所以可以這樣寫
flag = False
if flag: break # 已經排序完成 提前跳出
print(*lst) # 把lst unpack 再print
```
```python
# 插入排序法 Time: O(n²), Space: O(1)
# 每一輪循序找出lst[i-1] > lst[i]的地方 把lst[i] 那項往前移 直到前一個比他小
lst = [int(i) for i in input().split()]
i = 1
while True:
while i < len(lst) and lst[i-1] <= lst[i]: # 往後找到開始降冪的地方
i += 1
if i == len(lst): break
while i >= 0 and lst[i-1] > lst[i]: # 往前交換 直到排序正確
lst[i-1], lst[i] = lst[i], lst[i-1]
i -= 1
i += 1
print(*lst)
```
```python
# 堆疊排序法 Time: O(nlogn), Space: O(1)
# 使用標準函式庫中的heapq模組 (感覺好敷衍)
from heapq import heapify, heappop
lst = [int(i) for i in input().split()]
# Linear Heapify Time: O(n), Space: O(1)
heapify(lst)
# Multiple Heappop Time: O(logn) for each, Space: O(1)
print(*[heappop(lst) for i in range(len(lst))])
```
```python
# 合併排序法 Time: O(nlogn), Space: O(n)
def merge(i, j): # 合併排序 [i, j)
if i == j-1: return [lst[i]] # 只有一個元素不用排序
# 分治 切一半
mid = (i + j) // 2 # 取中點
le = merge(i, mid) # 排序左邊
ri = merge(mid, j) # 排序右邊
# 合併
idx = i # 寫入lst起始位置
x = y = 0 # 左右串列的位置
while x < len(le) and y < len(ri):
# 左右取比較小的
if le[x] <= ri[y]:
lst[idx] = le[x]
x += 1
else:
lst[idx] = ri[y]
y += 1
idx += 1
# 把剩下的寫入
while x < len(le):
lst[idx] = le[x]
x += 1
idx += 1
while y < len(ri):
lst[idx] = ri[y]
y += 1
idx += 1
# 回傳排序後的區間
return lst[i:j]
lst = [int(i) for i in input().split()]
lst = merge(0, len(lst)) # 起始區間 [0, n)
print(*lst)
```
### 2. 循序搜尋
```python
# 自己手刻函式
def find(arr, target):
for idx, item in enumerate(arr):
if item == target: return idx # 找到第一個符合的
return -1 # 找不到return -1
target = int(input())
arr = [int(i) for i in input().split()]
if (idx := find(arr, target)) == -1: # 海象運算子:= 很可愛
print("無法找到搜尋目標數字")
print("搜尋次數:", len(arr), sep="")
else:
print("發現搜尋目標數字,索引值為", idx, sep="")
print("搜尋次數:", idx + 1, sep="")
```
```python
# 使用生成器推導式 以next(generator, default)函式找出第一個符合的
target = int(input())
arr = [int(i) for i in input().split()]
# 整個next()的功能和上面的find一模一樣 (用海象的話就太長了 分兩行寫)
idx = next((idx for idx, item in enumerate(arr) if item == target), -1)
if idx == -1:
print("無法找到搜尋目標數字")
print("搜尋次數:", len(arr), sep="")
else:
print("發現搜尋目標數字,索引值為", idx, sep="")
print("搜尋次數:", idx + 1, sep="")
```
## 三、語法整理
1. **進階語法:**
- `[expr for var in iterable if condition]`: 各種推導式
- `if-else`: 三元運算子
- `lambda`: 匿名函式
- `:=`: 海象運算子 回傳並賦值
2. **內建函式:**
- `eval`: 動態運算函式
- `split`: 字串切割函式,以分割字元將字串切割成列表
- `join`: 字串連接函式
- `range`: 區間生成函式
- `enumerate`: 列舉函式,同時獲取索引和元素值
- `next`: 迭代器取值函式
3. **函式庫:**
- `sys .stdout .stdin`: 標準輸出和標準輸入
- `heapq .heapify .heappop`: 堆排序相關函式庫