###### tags: `資訊科技`
# 程式設計(使用Python、ZeroJudge)
## 零、評量、學習歷程
### 1. 評量方式
+ 上課基本練習(遲交期限:1週) **40%**
+ 作業題數 **20%** (期中10%+期末10%)
- 作業登記表:[103](https://docs.google.com/spreadsheets/d/1Ftcil7r6wpAnPucz3zF9pd7iC_5VP63wykgbAJPIj9w/edit?usp=sharing)、[104](https://docs.google.com/spreadsheets/d/1QLfSVBIxS9xOFxaog1N5YDTIsofhI_-OhHallVQt590/edit?usp=sharing)、[106](https://docs.google.com/spreadsheets/d/1rtZrk_LzjXbvl84E1Ge-YFCWcXB7tnOstrU2xlsjEpE/edit?usp=sharing)
- [歷年作業登記表](https://hackmd.io/@cube/r1Cw2JgDT)
- 每寫完一題作業,請將程式碼連結登錄於作業登記表,以統計作業題數。請小心不要改到別人的資料。惡意編刪別人的資料,視情節扣分或校規處理。
- 作業原始分數:解題數 $*$ 6 (最高120分)
```
if 上機考分數>=60
作業實得分數=作業原始分數
else
作業實得分數=作業原始分數*(上機考成績/60)
```
- 不要為了衝題數,做複製貼上、不求甚解這種沒意義的事。上機考0分,全部都寫也是0分。
- 不寫作業,除了無作業成績,上機考時網路會斷線,沒有任何參考資料,也必定寫不出來,請每個單元至少完成 3 題作業,熟練基本語法。**(不寫作業被當的機會很高,除非你有本事上機考2次都及格)**
- 不要考前才寫作業,初學程式會有很多錯誤,要花時間除錯。請自我要求每週至少要寫 1 題作業,上機考才會比較保險。
- 不會的可以去參考網路上的程式碼、解法,同學也可以互相討論,而且是鼓勵的。不論如何,都要在了解解法後,不看別人的程式碼,自己親自寫一遍。
- 有做作業,考差了才有補救的機會,作業題為期末解題報告的題目。
+ 期中上機考(迴圈教完後 1 週) **20%**
+ 期末上機考(倒數第 2 週) **20%**
+ 期末解題報告 **10%**
- 非必要,想高分或不及格的同學請保握最後機會。
- 繳交期限:最後一週上課前 1 天。
- 分數:每一題 10 分。每個單元至多可放 2 題 (不可以都寫同一單元的題目)
- 報告格式:
* 第1頁為解題目錄(單元、題號、題目、頁碼)。
* 每題的子標題為
(1) 單元、題號、題目、題目簡述
(2) 解題動態、評分結果截圖
(3) 解題思路
(4) 程式碼
(5) 反思(遇到的錯誤、修正的地方、更好的方法…)
(6) 錯誤程式碼
- 檢核方式:
* 有交解題報告者,最後一週會請你在沒有網路的狀態下重寫一題當做檢核(題目由老師挑選),寫不出來作業直接作廢不算分,請務必自行思考完成。
* 不要為了分數直接複製貼上別人的程式碼,那是無意義的行為,檢核時你就會現出原形,就不用做這種白工了。
- 可整合上課內容後完成課程學習成果,上傳至學習歷程檔案平台。請儘量挑選一開始有錯,然後修正的題目,將修正的想法寫出來更能顯示出反思的能力。
+ 如果對寫程式有興趣並要參加APCS檢定,下學期多元選修可以選修APCS(大學程式設計先修檢測)程式實作,挑選標準主要為ZJ的解題數(請寫在多元選修意向書裏)。
### 2. [TOI推廣計畫-線上練習賽](https://tpmso.org/toi/index.php/reg/)
+ 成績計算:分數/100直接加在總成績。
+ 上學期10、11、12月,下學期3、4、5月,最後一週。
+ 星期一08:00 ~ 星期五20:00。90分鐘。
+ [證書](https://drive.google.com/open?id=1DcgDKn1R33kOPc_HazdIyQDgyYxSCPlZ)
### 3. [APCS](https://apcs.csie.ntnu.edu.tw/)
+ 實作級分*2,直接加在總成績。
+ 4級分免上機考,上機考成績為100。
+ 5級分以上者,一切皆免,學期成績直接算100。
### 4. 學習歷程檔案(修課記錄、課程學習成果)
+ 最後一週上課結束前如果認證完成,學期總成績加分。
+ [撰寫「課程學習成果」參考資源](https://hackmd.io/@cube/HkCv90e19)。
### 5. 基礎教學網站
+ [Teach Python 3 and web design with 200+ exercises Learn Python 3 - Snakify](https://snakify.org/en/)
+ [tutorialpoint](https://www.tutorialspoint.com/python/index.htm)
+ [w3cschool](https://www.w3schools.com/python/)
### 6. Python APCS(中正大學 吳邦一教授)
+ [PythAPCS123講義](https://drive.google.com/drive/folders/1mnVdO2LHq7e4vesn6pt_R0-S6YWtz4Q4?fbclid=IwAR2Xo7LP8V3lWyhJEbFx3F8JLF9AIEI9t9snla9vwwtI4qlGc0mDwJVuf1o)、[PythAPCS123 YouTube撥放清單](https://youtube.com/playlist?list=PLpmg1QLbgMuSIDOgOcwf0Fbbn2ZDR7s-X
)
+ [AP325(Python)](https://hackmd.io/@bangyewu/Hy2kbYLI6/%2Fg2kqHh5_Q4eQnz-mfNu3Kw)、[範例程式](https://drive.google.com/drive/folders/1JziPJ39tANRokjx6nFzZSRXtym0p5_kg?fbclid=IwAR2Xo7LP8V3lWyhJEbFx3F8JLF9AIEI9t9snla9vwwtI4qlGc0mDwJVuf1o)
+ [PyAP45_v202201題解講義](https://drive.google.com/drive/u/0/folders/10hZCMHH0YgsfguVZCHU7EYiG8qJE5f-m)、[PyApcs45 YouTube撥放清單](https://www.youtube.com/playlist?list=PLpmg1QLbgMuRQXHRkX9iDHyAVIW1D6OJF
)
### 7. 軟體
+ [Google Colaboratory](https://colab.research.google.com/)
- [Google Colab相關設定](https://hackmd.io/@wiimax/HJuUPnPQr)
+ [The collaborative browser based IDE - Replit](https://replit.com/)
- 「+ Create Repl」 可新增一個 Repl (專案)
- Template 欄選擇 「C++」 或 「Python (with Prybar)」,Title 欄填入專案標題如 a001, 再按「+ Create Repl」鈕,就會進入專案編輯的頁面。
- 如果 Template 沒有看到 Python (with Prybar) ,請自行輸入 prybar 後按「Search community templates」後點找到的「Python (with Prybar)」,按「+ Use Template」/「Use Template」,回首頁重新整理後,「Python (with Prybar)」即會出現在 「Favorites」項目下。
- Repls:專案管理
New folder:建立分類資料夾,如 ch1、ch2 …。
專案.../Move:將專案移至分類資料夾。
- 側邊欄/Tools/User Settings/Indentation Size:4
- 側邊欄/Tools/User Settings/ser Settings/AI Code Completion:關閉
- 側邊欄/Tools/User Settings/Themes:Explore Themes/VS Code Dark/Use Theme
+ [GDB online Debugger | Compiler - Code, Compile, Run, Debug online C, C++](https://www.onlinegdb.com/)
+ [Online Python](https://www.online-python.com/)
+ [Thonny](https://thonny.org/) (安裝套件: Tools/Manage plug-ins)
+ [Python IDLE 完整安裝教學](https://simplelearn.tw/2022/07/30/python-%E4%BB%8B%E7%B4%B9%E5%8F%8A%E5%AE%89%E8%A3%9D%E6%95%99%E5%AD%B8-2022%E6%9B%B4%E6%96%B0%E7%89%88/)
## 一、輸出與輸入、變數、運算式與運算子
### 1. 輸出與輸入
+ 變數=input(\[提示字串\])
+ print(項目1\[,項目2,...\])
- 字串要加 ' ' 或 " "
- 可用 + 將字串連接
- print() 輸出後,預設會自動補上換行符號。
- 印出多個項目,預設以一個空白間隔。
``` python
print('Hello Python') # 印出一段文字
print('Hello', 'Python', 123) # 印出多個項目,預設以一個空白間隔
print('Hello', 'Python', 123, sep=',') # 以『,』為項目間的分隔符號
```
+ print('A=%d B=%d C=%d' %(A, B, C))
- [Python 3 print 函数用法总结](http://www.runoob.com/w3cnote/python3-print-func-b.html)
+ print('A={} B={} C={}'.format(A, B, C))
- {} 的位置會被後方 format 所帶的參數所取代,預設會依照順序輸出。
- [Python Format String 字串格式化整理](https://blog.jaycetyle.com/2018/01/python-format-string/)
+ print(f'A={A} B={B} C={C}')
- [f-string 是 Python 3.6 才有的方法](https://myapollo.com.tw/blog/python-f-string-formating-syntax/#google_vignette)
:::info
EX_1_1:[d483: hello, world](https://zerojudge.tw/ShowProblem?problemid=d483)
+ Colab 快速鍵
- `Ctrl+Enter`:執行目前程式
- `Ctrl+a`:全選
- `Ctrl+c`:複製
- `Ctrl+v`:貼上
- `Ctrl+x`:剪下
- `Ctrl+s`:儲存
- `Ctrl+z`:復原
- `Ctrl+滾輪`:放大、縮小
- `Shift`+方向鍵、`Home`、`End`:選取程式
+ Replit 快速鍵
`Ctrl+Shift+v`:Replit 測資貼上。或右鍵/貼上。
+ Thonny 快速鍵
`F5`:執行目前程式
:::
:::info
EX_1_2:[a001: 哈囉](https://zerojudge.tw/ShowProblem?problemid=a001)
``` python
s=input('please input a string:') # 輸出提示訊息後等使用者輸入,但 OJ 不可輸出規定以外的東西。
s=input()
print('hello,',s)
```
:::
### 2. 變數與資料型態
+ 變數:存放資料的記憶體空間(名稱自訂)
+ 數值型態:int(整數)、float(浮點數、小數)、bool(True、False)
+ 字串型態:' ' 或 " " 中的文字
+ 容器型態:
- list:有順序、可變動的資料集合
- tuple:有順序、不可變動的資料集合
- set:無順序的資料集合
- dict:鍵值對(key-value)的集合
+ 等號的意義是『賦值』(assignment),不是『等於』,把等號右邊計算完的值指定給等號左邊的變數(左邊一定是變數(記憶體位置))。
- 錯誤:a+5=7
- a,b=1,2
+ 資料型態轉換:int()、float()、str()
- int(): 字串或浮點數轉整數
- str(): 數字轉字串
- float(): 字串轉浮點數
:::info
EX_1_3:[d049: 中華民國萬歲!](https://zerojudge.tw/ShowProblem?problemid=d049)
``` python
s=input() # 讀入的為字串
y=int(s) # 將字串轉換為整數,整數才能做算數運算加減乘除
y=int(input()) # 上兩行整合
```
:::
:::info
EX_1_4:[a002: 簡易加法](https://zerojudge.tw/ShowProblem?problemid=a002)
+ 需要同一行輸入兩個整數(空白間隔)時,可用 str.split() 將 str 字串分割成數個子字串(以空白區分)
``` python
s=input().split() # s=['1','2']。s[0]、s[1]
a=s[0]
b=s[1]
print(a+b) # Q:輸入「1 2」,會印出?
```
+ map(某函式名, list) 會把某函式依次作用到list的每個元素上
``` python
s=input().split() # s=['1','2']。s[0]、s[1]
a=int(s[0])
b=int(s[1])
a,b=input().split() # a='1', b='2'
c=int(a) # c=1
d=int(b) # d=2
a,b=input().split() # a='1', b='2'
a=int(a) # a=1。Python 支持動態類型,變數的類型可以在運行時改變,C++不行。
b=int(b) # b=2
a,b=map(int, input().split())
```
:::
:::info
EX_1_5:[d489: 伏林的三角地](https://zerojudge.tw/ShowProblem?problemid=d489)
+ 以[海龍公式](https://zh.wikipedia.org/zh-tw/%E6%B5%B7%E4%BC%A6%E5%85%AC%E5%BC%8F)求三角形面積。
+ 「*」不可省略。
+ 除錯第一步,檢查變數的值。
+ 先乘除後加減,可用小括號改變運算順序。
+ 運算式裏不能用中、大括號,通通都用小括號。2 * [3 + (4 + 5) * 6] → 2 * (3 + (4 + 5) * 6)
+ 浮點數與整數運算後會變成浮點數,整數做『/』運算後也會變成浮點數。在OJ上,答案36.0與36是不一樣的,要注意輸入、輸出的說明。
+ 明明程式都對,但出現錯誤。
- 之前程式碼錯誤造成,如print=(int(area))。如果程式碼已沒有錯誤,『執行階段/重新啟動工作階段』。
``` python
TypeError Traceback (most recent call last)
<ipython-input-21-678cc0bd0ae2> in <cell line: 4>()
2 s=(a+b+c)/2
3 area=s*(s-a)*(s-b)*(s-c)
----> 4 print(int(area))
TypeError: 'int' object is not callable
```
:::
:::warning
[a861: 1. Secure the Perimeter](https://zerojudge.tw/ShowProblem?problemid=a861)
+ 「*」不可省略。
+ 先乘除後加減,可用小括號改變運算順序。
+ 運算式裏不能有中括號、大括號。2 * [3 + (4 + 5) * 6] → 2 * (3 + (4 + 5) * 6)
+ EOF 結尾的測資
``` python
while True:
try:
~
~
except:
break
```
+ Python 以冒號「:」及縮排來表示程式區塊。
- if、else、elif、for、while 等為會使用到程式區塊的關鍵字,在其「:」之後的下一行的就必須縮排。
- 以`Tab`鍵縮排,預設為2個空格。Colab縮排寬度調為4。
- `Tab、Shift+Tab`:增、減縮排
:::
:::warning
[d461: 班際籃球賽](https://zerojudge.tw/ShowProblem?problemid=d461)
:::
:::warning
[d053: 10970 - Big Chocolate](https://zerojudge.tw/ShowProblem?problemid=d053)
+ EOF 結尾的測資
``` python
while True:
try:
~
~
except:
break
```
:::
### 3. 算數運算子
| 算數運算子 | 意義 | 備註|
|:-------- |:------ |:-------|
| + | 加 | |
| - | 減 | |
| * | 乘 | |
| / | 除 |17/5 為 3.4,15/5 為 3.0 |
| // | 取商數 |17//5 為 3</br> 17.0//5 為3.0 |
| % | 取餘數 |17%5 為 2 |
| ** | 次方 | 5**2 為 25 |
:::info
EX_1_6:[d050: 妳那裡現在幾點了?](https://zerojudge.tw/ShowProblem?problemid=d050)
+ 取餘數:%
+ [常用運算子的優先順序](https://sites.google.com/site/jingprogrampy/python/%E9%81%8B%E7%AE%97%E5%AD%90%E9%81%8B%E7%AE%97%E5%BC%8F),以海龍公式解釋。
:::
:::info
EX_1_7:[d485: 我愛偶數](https://zerojudge.tw/ShowProblem?problemid=d485)
+ 將 a 調整為後一個偶數, b 為前一個偶數,[計算等差數列項數](https://zh.wikihow.com/%E8%AE%A1%E7%AE%97%E7%AD%89%E5%B7%AE%E6%95%B0%E5%88%97%E4%B8%AD%E7%9A%84%E9%A1%B9%E6%95%B0)。
+ a 偶數 a=a+0,a 奇數 a=a+1
- a=a+a%2
+ 複合指定運算子(a=a+5 → a+=5)
+ 整數除法://
:::
:::info
EX_1_8:[e343: BMI 計算](https://zerojudge.tw/ShowProblem?problemid=e343)
+ 輸入分兩行讀入。
+ 字串轉浮點數。
+ 次方:**
+ 小數點位數控制
- 參考解題報告:round。 試著印出bmi=22.7
print('bmi=', round(bmi,1), sep='')
- 參考 一、1. 輸出與輸入
print(f'bmi={bmi:.1f}')
print(f'{bmi:.1f}')
:::
:::warning
[d073: 分組報告](https://zerojudge.tw/ShowProblem?problemid=d073)
+ 整數除法://
:::
:::warning
[c379: 成為出題者](https://zerojudge.tw/ShowProblem?problemid=c379)
+ 整數除法://
:::
:::warning
[d827: 買鉛筆](https://zerojudge.tw/ShowProblem?problemid=d827)
+ 整數除法://
+ 取餘數:%
:::
:::warning
[b757: 頸美椰子樹](https://zerojudge.tw/ShowProblem?problemid=b757)
+ 除:/
+ print(f'{變數名:g}') 根據數值大小採用科學符號 {變數名:e} 或浮點數 {變數名:f}。
+ {變數名:g} 如果小數點為0,不會輸出。
:::
:::warning
[a862: 2. My Dear Friend VIR](https://zerojudge.tw/ShowProblem?problemid=a862)
+ 除:/
+ v,r=map(float,input().split())
+ 小數點位數控制。
+ EOF 結尾的測資。
``` python
while True:
try:
~
~
except:
break
```
:::
:::warning
[f651: 開關燈](https://zerojudge.tw/ShowProblem?problemid=f651)
+ 整數除法://
+ 觀察n=1~10,找規律。類似d073。
+ EOF 結尾的測資。
``` python
while True:
try:
~
~
except:
break
```
:::
### 4. 關係運算子
| 關係運算子 | 意義 | 備註|
|:-------- |:------ |:-------|
| == | 等於 | =是賦值,==是判斷是否相等 |
| != | 不等於 ||
| > | 大於 ||
| >= | 大於等於 ||
| < | 小於 ||
| <= | 小於等於 ||
:mega: python 可以用 1 < x < 9 ,其它語言不行,該如何? 1<x and x<9
### 5. 邏輯運算子
| 邏輯運算子 | 意義 | 備註|
|:-------- |:---- |:---|
| and | 而且 ||
| or | 或者 ||
| not | 否 ||
## 二、選擇
### 1. if 條件式語法
``` python
if 條件:
條件「成立」時的程式碼
```
:mega: if 後要加「:」
:mega: python 沒有如 C++ 的大括號 { } 來表示程式區塊,沒縮排、縮排錯誤都會有問題。
:::info
EX_2_1:[a012: 10055 - Hashmat the Brave Warrior](https://zerojudge.tw/ShowProblem?problemid=a012)
+ Q:以下的程式會發生什麼問題?
``` python
if ans<0:
ans=-ans
print(ans)
```
:::
:::warning
[a799: 正值國](https://zerojudge.tw/ShowProblem?problemid=a799)
:::
:::warning
[d068: 該減肥了!](https://zerojudge.tw/ShowProblem?problemid=d068)
:::
:::warning
[o578. 起司 (Cheese)](https://zerojudge.tw/ShowProblem?problemid=o578)
+ 先把答案的初值設為 0。
+ 如果 L、W、H 除以 K 的餘數都為 0,則答案改為 (L//K)\*(W//K)\*(H//K)
:::
:::warning
[b682: 2. 同學早安](https://zerojudge.tw/ShowProblem?problemid=b682)
+ [提示](https://zerojudge.tw/ShowThread?postid=16450&reply=0)
+ 將時間全部轉成分鐘會比較好做,分鐘的時間差以//、%轉回小時、分。
+ 因為校長最久只會站23小時59分,所以如果開始時間大於結束時間,表示站隔夜,結束時間要多加1440(24小時)。
:::
### 2. if~else 語法
``` python
if 條件:
條件「成立」時的程式碼
else:
條件「不成立」時的程式碼
```
:mega: else:後面不要寫條件。
:::info
EX_2_2:[d064: ㄑㄧˊ 數?](https://zerojudge.tw/ShowProblem?problemid=d064)
:::
:::info
EX_2_3:[d066: 上學去吧!](https://zerojudge.tw/ShowProblem?problemid=d066)
+ if h>=7 and m>=30 and h<17: → 幾點會造成錯誤?
+ if (8<=h<17) or (7點的狀況):
+ and、or
+ [常用運算子的優先順序](https://sites.google.com/site/jingprogrampy/python/%E9%81%8B%E7%AE%97%E5%AD%90%E9%81%8B%E7%AE%97%E5%BC%8F)
:::
:::warning
[b877: 我是電視迷](https://zerojudge.tw/ShowProblem?problemid=b877)
:::
:::warning
[f373: 週年慶 Anniversary](https://zerojudge.tw/ShowProblem?problemid=f373)
+ 分別計算兩百貨折扣後的金額,比較大小輸出。
:::
:mega: 如果測資的第一行有一個整數t,代表測試的筆數,要用以下的寫法。
``` python
t=int(input())
for _ in range(t):
~ # 程式碼
```
:::warning
[e948: 1. 基礎代謝率 (BMR Calculation)](https://zerojudge.tw/ShowProblem?problemid=e948)
+ 輸入的第一行有一個整數n,代表測試筆數。
:::
:::warning
[f043: 1. 小豪的回家作業 (Homework)](https://zerojudge.tw/ShowProblem?problemid=f043)
+ 給定兩整數R、A,求出A+B=R的B值後輸出。
+ 如果R=A,則先將A-3再求B。
+ A、B小的寫在算式的前面。
:::
### 3. 巢狀 if 語法
``` python
if 條件1:
if 條件2:
條件1「成立」,且條件2「成立」時的程式碼
else:
條件1「成立」,且條件2「不成立」時的程式碼
else:
條件1「不成立」時程式碼
```
:mega: if 或 else 的程式區塊內,都可再增加條件式。
:::info
EX_2_4:[d058: BASIC 的 SGN 函數](https://zerojudge.tw/ShowProblem?problemid=d058)
+ if n>0: vs. if n>=0:
:::
:::info
EX_2_5:[a006: 一元二次方程式](https://zerojudge.tw/ShowProblem?problemid=a006)
+ 開根號可用**0.5
+ Q:d>0時,先試著自行寫出x1,x2公式。
- 需除錯時,Colab 可+程式碼區塊,詢問變數內容。
- a=2, b=3, c=1, x1=-0.5, x2=-1
+ d==0時,還是要有x1的計算過程。執行時,不會去執行不符合條件的程式碼。
a=2, b=4, c=2, x1=-1
+ [Python f-string 各種格式使用方法](https://myapollo.com.tw/blog/python-f-string-formating-syntax/#google_vignette)
+ 練習用 Thonny 「除錯目前程式」看條件式執行流程。
+ 註解
- 單行: \#
- 多行:「'''」開頭(三個單引號),「'''」結尾。
在 Colab 中,可選取多行,再按 `ctrl + /` 完成多個單行註解。
:::
:mega: 逐行除錯
+ Thonny
(1) 執行目前程式(F5)後發現錯誤。
(2) 點行號設定中斷點(可跳過沒問題的程式)。
(3) 按「![截圖 2024-09-05 下午2.36.26](https://hackmd.io/_uploads/SJNq-0I3A.png =20x20) 為目前腳本除錯」,準備逐行執行。
(4) 檢視/變數,開啟變數面板,可以看到執行每一步的變數變化。
(5) 逐行執行
跳過(Step Over)(F6):黃色區塊一次執行(big step)。
跳入(Step into)(F7):詳細執行每個小步驟(small step)。
(6) 發現錯誤後按『STOP』停止除錯,修正程式。
+ Google Colab
(1) 執行目前程式(Ctrl+Enter)後發現錯誤。
(2) 於有問題程式碼前加入breakpoint() (執行到中斷點,可跳過沒問題的程式)。
(3) Pdb 指令
| 指令 | 功能 |
| ----| ----- |
| n(next) | 執行當前行,並移動到下一行,不進入函數內部|
| s(step) | 進入函數內部逐步執行|
| c(continue) | 繼續執行到下一個中斷點或程式結束|
| p <變數名> | 印出變數的值。例如p score 會印出 score 變數的值|
| q(quit) | 離開 pdb|
| h(help) | 指令說明|
+ [Replit](https://docs.replit.com/programming-ide/workspace-features/debugging)
(1) 執行目前程式(Ctrl+Enter)後發現錯誤。
(2) 打開除錯視窗(Debugger),並將其拖曳至適當位子(不要和Console在同一窗格)。
(3) 於行號前設定中斷點(可跳過沒問題的程式)。
(4) 按除錯視窗的『RUN』。
(5) 使用『Next Step』或『Skip Step』或『Next Breakpoint』逐行執行,觀察流程和變數的變化。
(6) 發現錯誤按『Stop』停止除錯,修正程式。
:::warning
[a003: 兩光法師占卜術](https://zerojudge.tw/ShowProblem?problemid=a003)
:::
:::warning
[d065: 三人行必有我師](https://zerojudge.tw/ShowProblem?problemid=d065)
:::
:::warning
[f165: 棒棒糖事件](https://zerojudge.tw/ShowProblem?problemid=f165)
+ 判斷棒棒糖數除以小朋友人數的餘數r是否為0,當r=0時,輸出「OK!」,反之輸出r。
+ 小朋友人數可能為0,不會搶成一團,所以蝸牛老師不需吃下任何棒棒糖,輸出「OK!」。
+ 先排除小朋友人數為0的狀況,不然「%」運算會錯誤。
:::
:::warning
[b899: 2. 物品探測](https://zerojudge.tw/ShowProblem?problemid=b899)
+ 分別計算三點間的距離,最長的為正方形的對角線。
+ [正方形四點 A、B、C、D,假設 A、C 為對角,則 D = A + C - B。](https://zerojudge.tw/ShowThread?postid=16940&reply=13550#16940)
:::
### 4. 多重選擇 if\~elif\~else 語法
``` python
if 條件1:
條件1「成立」時程式碼區塊
elif 條件2:
條件1「不成立」,且條件2「成立」時的程式碼
elif 條件3:
條件1、2「不成立」,且條件3「成立」時的程式碼
...
else:
上述條件都「不成立」時的程式碼
```
:mega: else if()可視需要增加。
:::info
EX_2_6:[d460: 山六九之旅](https://zerojudge.tw/ShowProblem?problemid=d460)
+ elif 6<=a<=11: v.s. elif a <= 11:
- C++ 需以 a>=6 and a<=11 的概念來寫
+ 單用 if,不用 elif 可以嗎?
``` python
if a<=5:
print(0)
if a<=11:
print(590)
```
:::
:::warning
[f337: 同樂會 (Party)](https://zerojudge.tw/ShowProblem?problemid=f337)
:::
:::warning
[b676: 63萬勞工苦輪班不像人像機器](https://zerojudge.tw/ShowProblem?problemid=b676)
:::
:::warning
[a053: Sagit's 計分程式](https://zerojudge.tw/ShowProblem?problemid=a053)
:::
:::warning
[c382: 加減乘除](https://zerojudge.tw/ShowProblem?problemid=c382)
+ 先不要使用 eval(),練習多重選擇。
+ 輸入使用split()先分割就好,要計算時再轉成int。
:::
## 三、迴圈
### 1. range 函式
+ 串列變數=range(整數)
- 產生0~「整數-1」的串列
+ 串列變數=range(起始值,終止值)
- 產生起始值~「終止值-1」的串列
- 左閉右開區間
+ 串列變數=range(起始值,終止值,間隔值)
- 產生:起始值, 起始值+間隔值, 起始值+間隔值*2, ...
+ [Python range() 函数用法](http://www.runoob.com/python/python-func-range.html)
### 2. for 迴圈語法
``` python
for 變數 in range(重複次數):
程式碼
```
``` python
for 變數 in 串列:
程式碼
```
``` python
for 變數 in 字典: # 變數會儲存字典的key
程式碼
```
``` python
break:強制跳出「整個」迴圈
continue:強制跳出「此次」 迴圈,繼續進入下一次圈
```
``` python
for 變數 in 串列或字串:
程式碼
else:
迴圈正常結束,執行此區塊程式碼。(break不會執行)
```
:::info
EX_3_1:[d498: 我不說髒話](https://zerojudge.tw/ShowProblem?problemid=d498)
+ 迴圈變數名:i 或 _
+ [字串中輸出單引號](https://blog.csdn.net/menghuanshen/article/details/104289192)
+ 練習用 Thonny 「除錯目前程式」看迴圈執行流程。
+ range 3 種參數寫法。
:::
:::info
EX_3_2:[d491. 我也愛偶數 (swap 版)](https://zerojudge.tw/ShowProblem?problemid=d491)
+ Q:先完成 a+...+b,會有錯誤?
A:sum 初值要歸零。雖然python變數不需要事先宣告,但它沒厲害到可以沒初值,就直接放在表達式中去進行運算(沒有賦值會不知道該變數是什麼類型,預設為'內建函數或方法',因而無法判斷能否進行運算)。
+ 課堂加分:自行完成加偶數的部份。
+ python 兩變數交換:a,b=b,a
+ C不能這樣寫
``` c
t=a;
a=b;
b=t;
```
:::
:::info
EX_3_3:[h658: 捕魚 (Fishing)](https://zerojudge.tw/ShowProblem?problemid=h658)
+ 先計算魚夫和每個魚群的距離,第2筆測資:7.07 2.23 3.16
- 開根號可用**0.5,d=((x-a)\**2+(y-b)\**2)**0.5
+ 課堂加分:輸出最小值的距離。
- min_d(最小距離)的初值可假設為一個比可能最大值還要大的值(如1000)。
- 讀入每個魚群的中心座標(a,b),計算魚夫和魚群的距離,如果比目前的最小距離小,則記錄此時的最小距離和座標(min_a,min_b)。
+ [蛇形命名法](https://zh.wikipedia.org/zh-tw/%E8%9B%87%E5%BD%A2%E5%91%BD%E5%90%8D%E6%B3%95)
:::
:::warning
[b970: 我不說髒話 (續)](https://zerojudge.tw/ShowProblem?problemid=b970)
+ range範圍
+ 數字和『.』中間沒有空白。
+ [Python f-string 各種格式使用方法](https://myapollo.com.tw/blog/python-f-string-formating-syntax/#google_vignette)
:::
:::warning
[a244: 新手訓練 ~ for + if](https://zerojudge.tw/ShowProblem?problemid=a244)
:::
:::warning
[f338: 后羿射日(Archer)](https://zerojudge.tw/ShowProblem?problemid=f338)
+ 距離用 R**2,不需開根號。
:::
:::warning
[f605: 1. 購買力](https://zerojudge.tw/ShowProblem?problemid=f605)
+ 找出3物品最大值和最小值,可使用max、min函式。
:::
:::warning
[f312: 1.人力分配](https://zerojudge.tw/ShowProblem?problemid=f312)
+ 以for迴圈枚舉所有可能的工人分配方法。
+ 求最大值可用max函式或if。
:::
### 3. list 簡介
+ list(串列) 把很多元素串起來,依照排列的順序給予編號 0, 1, 2,...
+ 同一行輸入元素個數不定時,需以 list 處理。
``` python=
a=[3,5,7,1,2]
print(a)
print(a[2]) # 第四章會再詳細介紹 slice
for n in a:
print(n) # 每印一個元素換行
for i in range(len(a)): # 以索引值存取
print(a[i])
for n in a:
print(n, end=' ') # 每行以空白結尾
print(*a) # 印出每個元素。「*」可將序列分解成多個獨立的元素(不在賦值語句中使用*號)
print(*a, sep=',') # 可以更改分隔符號
Q:如何用 for 做到? 直接 print(n, end=',') 最後會多出一個「,」
for n in a:
print(n, end=',') # 每行以「,」結尾
Hint:以索引值的方式,分段處理(先印出前4個元素以「,」結尾,再印出最後一個元素)。
```
<font color="#fff">
for i in range(len(a)-1):</br>
print(a[i], end=',')</br>
print(a[len(a)-1])
</font>
+ list常用的計算函式
| 串列函式 | 意義 |
|:------------ |:-------------- |
| lst=list() 或 lst=[] |宣告空的串列|
| len(lst) | 回傳串列個數 |
| max(lst) | 回傳串列中的最大值 |
| min(lst) | 回傳串列中的最小值 |
| sum(lst) | 將串列元素加總 |
:::info
EX_3_4:[j178: 手遊廣告 (Advertisement)](https://zerojudge.tw/ShowProblem?problemid=j178)
+ 同一行輸入兩個整數(空白間隔)
- m, a = map(int, input().split())
+ 同一行的多個元素轉成 list (元素個數可不定)
- val = [*map(int,input().split())]
- val = list(map(int,input().split()))
- (四.1再說明)val = [int(x) for x in input().split()] # 使用列表生成式(list comprehension),將讀進來的字串轉成整數後放入一個list。
+ Q:如果程式寫成
``` python
for t in val:
if a>t:
a+=t
```
以下測資的正確答案為25,但會輸出?
4 10
5 10 30 10
+ 迴圈中斷
- break:強制跳出「整個」迴圈。
- continue:強制跳出「此次」 迴圈,繼續進入下一次圈。
``` python
for i in range(10):
if i==5:
break # continue
print(i)
```
:::
:::info
EX_3_5:[f708: 蟲蟲危機 (Insect)](https://zerojudge.tw/ShowProblem?problemid=f708)
+ 串列元素加總
``` python
val=[1,2,3]
sum=0
for t in val:
sum+=t
print(sum)
```
+ sum(lst) 將串列元素加總
:::
:::warning
[d046: 文文採西瓜](https://zerojudge.tw/ShowProblem?problemid=d046)
``` python
watermelon = [*map(int,input().split())]
watermelon = list(map(int,input().split()))
watermelon = [int(x) for x in input().split()]
```
:::
:::warning
[b138: NOIP2005 1.陶陶摘苹果](https://zerojudge.tw/ShowProblem?problemid=b138)
:::
### 4. 巢狀迴圈語法
+ Q:在日常生活中,有什麼事像巢狀迴圈的概念?
``` python
for i in range(外圈次數):
for j in range(內圈次數):
程式碼
```
+ 九九乘法表
``` python
for i in range(1, 10):
for j in range(1, 10):
print(f'{i}x{j}={i*j}', end=' ') # end=' ' 表示每行以空白結尾
print() # 內層迴圈執行結束後才換行
```
:::info
EX_3_6:[e621. 1. 免費停車 (Free Parking)](https://zerojudge.tw/ShowProblem?problemid=e621)
+ 先完成一天的狀態。
+ 免費停車位以空白隔開,輸出一筆之後才以print()換行。
+ 布林型態(True、False):free = False
+ not
:::
:::info
EX_3_7:[d660: 11764 - Jumping Mario](https://zerojudge.tw/ShowProblem?problemid=d660)
+ wall= [*map(int,input().split())]
+ 用 now 表示目前高度( 初值為 wall[0] ),每次和右牆比較完,調整其為右牆的高度。
- 以索引值存取較麻煩
``` python
for i in range(1,n):
if now < wall[i]:
~
else:
~
```
- 直接存取串列
``` python
for w in wall[1:n]: # wall[1:]索引值留白表示取到最後一個
if now < w:
~
else:
~
```
+ 先用if else 且漏調目前高度,練習除錯。(if else 說明 F7 慢慢按,觀察變數變化)
:::
:::warning
[d786: 三、平均值](https://zerojudge.tw/ShowProblem?problemid=d786)
+ 每筆測資sum要歸零。
+ 每筆輸入 num=[*map(int,input().split())]
+ n=num[0]為數列長度。
+ 加總num[1]~num[n]後平均。
- for x in num[1:]:
- print(f'{sum/n:.2f}')
:::
:::warning
[c005: 10300 - Ecological Premium](https://zerojudge.tw/ShowProblem?problemid=c005)
+ 每筆測資獎金要歸零。
+ 運算式可先化簡避免除法誤差。
:::
:::warning
[c013: 00488-Triangle Wave](https://zerojudge.tw/ShowProblem?problemid=c013)
+ _ = input() # 第一列和測資間有一空白行要讀掉
+ 下半部 for j in range(A-1, 0, -1):
+ 印出數字不換行 print(j, end='')
+ 換行 print()
:::
### 5. while 迴圈語法
``` python
while 條件判斷: # 條件為「真」的時候繼續執行
程式碼
```
:::info
EX_3_8:[d189: 11150 - Cola](https://zerojudge.tw/ShowProblem?problemid=d189)
+ 請用 while 模擬換瓶過程,不可以直接套公式。
+ 先寫 n>3 以除錯看換瓶過程。最後剩 2 空瓶,可借 1 空瓶多換 1 瓶。
+ 整數除法://
``` python=
sum = ~ # sum 表示喝的可樂,一開始可以喝幾瓶? n 可以表示空瓶
while ~: # 還有 3 個以上的空瓶
~ # 更新喝的可樂數量 (加上利用空瓶換的可樂)
~ # 更新空瓶數量 (新換 + 剛換剩的)
~ # 最後剩 2 空瓶時
```
:::
:::warning
[c079: 10346 - Peter's Smokes](https://zerojudge.tw/ShowProblem?problemid=c079)
+ 類似 d189
:::
:::warning
[d570: 神龍見首不見尾](https://zerojudge.tw/ShowProblem?problemid=d570)
:::
:::warning
[d356: NOIP2002 1.级数求和](https://zerojudge.tw/ShowProblem?problemid=d356)
:::
:::warning
[f070: 1. 韓信點兵 (HanXin)](https://zerojudge.tw/ShowProblem?problemid=f070)
+ 因為答案很小,暴力解即可。
+ 以 while 迴圈,從1開始測,輸出符合條件的值。
:::
:::warning
[c350: “綠白黃” 四校聯課](https://zerojudge.tw/ShowProblem?problemid=c350)
+ ans+=(n/k)*w # 每次新換的電話號碼
+ n-=(n/k)*(k-w) # 因為 k > w,所以可以看成每一次的交換(k換w),新號碼會減少 (k-w) 個
:::
## 四、複合式資料型態
### 1. [list(串列)](https://www.twblogs.net/a/5cd7d860bd9eee67a77f8884)
+ 串列變數 = [ 元素1, 元素2, .... ] # 類似 C 的「陣列」。
+ 串列b = 串列a,不同於變數,不是將 a 複製到 b,兩者會有相同的記憶體位置。c = a.copy() 才會將 a 複製給 c。
``` python
a = [ 1, 2, 3]
b = a
print(a,b)
b[2] = 5
print(a,b)
c = a.copy()
c[2]=7
print(a,c)
```
+ 列表對「+」和「$*$」的操作與字串相似。「+」用予組合列表,「$*$」用於重複列表。
| 串列運算 | 範列 |
|:-------- |:-------------- |
| + |[1, 2]+[3, 4]為[1, 2, 3, 4]|
| $*$ |[1, 2]\*3為[1, 2, 1, 2, 1, 2]|
| x in lst |判斷x是否在串列, 3 in [1, 2, 3]為True|
| == |判斷兩串列是否相等, [1, 2]==[1, 2, 3]為False|
+ 運用 [] 取值,可以使用 index(索引值從0開始)、slice 來存取陣列裡的資料。假設lst,lst2為串列變數,常用的運算和方法如下表
- 編號由0開始。
- 區間定義都是左閉右開(不含右端)。
- 負的編號是倒數,最後一個是-1。
- 第一個編號不寫代表開頭,第二個編號不寫表示一直到結尾都包含。
- 完整的 slice 包含 list[start,stop,step],step 表示每次增加幾個位置,step=-1 會反轉 list。
| slice運算 | 意義 |
|:------------ |:-------------- |
| lst[i] | 取出索引值i的元素 |
| lst[-1] | 取出最後一個元素 |
| lst[i:j] | 取出索引值i~j-1的元素 |
| lst[i:j:k] | 取出索引值i~j-1的,間隔為k的元素 |
| lst[i:j]=lst2| 把索引值i~j-1的元素換成lst2的元素 |
| del lst[i:j] | 刪除索引值i~j-1的元素 |
``` python
lst = [0, 1, 2, 3, 4, 5]
lst[ :4:2]
lst[ : :3]
lst[ : :-1]
lst[2: :-1] # 從 idx 2 開始反向走到頭
```
+ 常用串列函式
| 串列函式 | 意義 |
|:------------ |:-------------- |
| lst=list() 或 lst=[] |宣告空的串列|
| len(lst) | 回傳串列個數 |
| max(lst) | 回傳串列中的最大值 |
| min(lst) | 回傳串列中的最小值 |
| sum(lst) | 將串列元素加總 |
| list('abc') | 將'abc'拆成'a','b','c'加入串列 |
| 串列方法(函式) | 意義 |
|:---------------|:-------------- |
| lst.append(x) | 將x附加到串列後面 |
| lst.insert(i,x)| 將x插入到索引值i的位置 |
| lst.extend(x) | 將串列x中的所有元素,附加到串列後面。<br />a=[1,2] b=[3,4] <br /> a.append(b) vs. a.extend(b)|
| lst.remove(x) | 刪除串列中的第一個x |
| lst.pop(i) | 回傳索引值i的元素,並將其刪除;<br/>如果沒有i,則傳回最後一個元素並刪除 |
| lst.index(x) | 回傳第一次出現x的索引值 |
| lst.count(x) | 計算出現x的次數 |
| lst.sort() | 將串列中的元素小->大排序,大->小則加入參數reverse=True |
| lst.reverse() | 將串列中的元素反轉 |
| lst2=lst.copy()| copy串列 |
| lst.clear() | 清除串列內所有元素 |
+ [列表生成式(List Comprehensions)](https://www.liaoxuefeng.com/wiki/1016959663602400/1017317609699776), 類似數學集合的表示法。$\{ 2n+1 \mid n \in \{0, 1, 2, 3, 4\} \} \rightarrow \{1,3,5,7,9\}$
- 以說明 list 內容的方式建構 list,把 for 迴圈包含在 list 建構中,可以是巢狀迴圈,甚至加 if 來過濾。
``` python
a = []
for i in range(5):
a.append(2*i+1)
a = [ 2*i+1 for i in range(5)]
b = [ x for x in a if x%3==0] # [3, 9]
val = [int(x) for x in input().split()] # EX_3_4 輸入,使用列表生成式(list comprehension),將讀進來的字串轉成整數後放入一個list。
```
:::info
EX_4_1:[g595. 1. 修補圍籬](https://zerojudge.tw/ShowProblem?problemid=g595)
+ 對於每一個 0,把它左右較小的數字取出加總
+ 左右邊界如果是 0,要特別處理,因為左邊界只有右邊鄰居而右邊界只有左邊鄰居。
:::
:::info
EX_4_2:[b558: 求數列第 n 項](https://zerojudge.tw/ShowProblem?problemid=b558)
+ [1-based indexing](https://xlinux.nist.gov/dads/HTML/oneBasedIndexing.html)
+ append()
:::
:::info
EX_4_3:[c299: 1. 連號或不連號](https://zerojudge.tw/ShowProblem?problemid=c299)
+ 輸入數列時,找出其最大值和最小值,可使用 if 或 max、min 函式。
``` python
val=[2,1,4,3]
mx=0 # 初值設一個極小值
for t in val:
if t>mx:
mx=t
print(mx)
```
+ 最大-最小+1==n,表示這個數列是連續的。
+ max()、min()
+ [] slice取值
+ 三元運算子
``` python
if a>b:
ans=a
else:
ans=b
ans=a if a>b else b
```
:::
:::info
EX_4_4:[b139: NOIP2005 2.校门外的树](https://zerojudge.tw/ShowProblem?problemid=b139)
+ 可以宣告一個整數串列tree(預設為1),索引值代表位置,值0、1表示有沒有樹。
+ Bonus:以 slice 運算,將索引 b~e 間的值換成0。
:::
<font color="#fff">tree[b:e+1]=[0]*(e-b+1)</font>
:::info
EX_4_5:[i071: 風景 (Landscape)](https://zerojudge.tw/ShowProblem?problemid=i071)
+ [1-based indexing](https://xlinux.nist.gov/dads/HTML/oneBasedIndexing.html)
h=[0]+[*map(int,input().split())]
+ 從小明家往左、往右檢查>小明家樓高的數量,錯誤的原因為?
+ 以變數(l_max、r_max)記錄小明家左邊、右邊最高樓高(初值為小明家樓高)。從小明家往左、往右檢查,如果檢查的樓高 > l_max、r_max,則答案+1,並調整 l_max、r_max。
+ 或往右發現有比小明家高的樓高,就讓小明家長高。(小明家高要先保留,往左檢查前要恢復原高)
+ slice
+ 變數名儘量小寫, r_max 和 r_Max是不同的,且因為變數不用宣告,迴圈內如果打錯也不知道。
:::
:::info
(進階)EX_4_6:[a693: 吞食天地](https://zerojudge.tw/ShowProblem?problemid=a693)
+ [1-based indexing](https://xlinux.nist.gov/dads/HTML/oneBasedIndexing.html)
food=[0]+[*map(int,input().split())]
+ 先試每次都重算 ➝ TLE
+ [時間複雜度](https://jason-chen-1992.weebly.com/home/time-space-complexity)
+ [前綴和](https://www.youtube.com/watch?v=VfL7dzFkW30),但不要用爆力法。
``` python
for i in range(1,n+1): # 對每個idx
for j in range(1,i+1): # 從頭開始加到此idx
pfx[i]+=food[j]
```
+ 1-based indexing 也可避免算前綴和 i=0 時,pfx[i]=pfx[i-1]+food[i] 會有 pfx[-1] 的錯誤。
:::
:::warning
[b127: 會議中心(Room)](https://zerojudge.tw/ShowProblem?problemid=b127)
+ [費式數列](https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97)
+ [0]*50
:::
:::warning
[f818: 物競天擇 (Survival)](https://zerojudge.tw/ShowProblem?problemid=f818)
+ 設一個變數存身高*體重的最小值,初值為1000005。
+ 進階可以使用 zip
- [python多個變數的for迴圈](https://www.itread01.com/content/1544266142.html)
- [Python zip()函數](http://www.runoob.com/python3/python3-func-zip.html)
- for h,w in zip(height, weight)
:::
:::warning
[f063: The Strongest Chain](https://zerojudge.tw/ShowProblem?problemid=f063)
+ 求每條鏈子最小值中,找出最大值。
+ max()、min()
+ [] slice取值
+ abs() 取絕對值
:::
:::warning
[c290. APCS 2017-0304-1秘密差](https://zerojudge.tw/ShowProblem?problemid=c290)
+ line = [int(x) for x in input()] # 把每一個數字字元轉換成整數後存入list
+ [] slice取值
:::
:::warning
[n631. 撲克 (Poker)](https://zerojudge.tw/ShowProblem?problemid=n631)
+ 因為牌只有52張,因此可以開一個大小為52的陣列(初始值皆為0),陣列的索引值代表牌的編號,值為牌的數量。poker=[0]*52
+ 讀入每個牌的編號,統計每張牌的數量(放在編號-1的位子)
+ 在不增加任何牌的情況下,以目前的牌最多能湊出幾副完整牌組:poker串列裏的最小值。
+ 若要用上所有現有的牌去湊出完整牌組,最少還需要補幾張牌:?(和串列最大值有關)
+ [解題參考](https://hackmd.io/@apcser/r16Vuk5ma?utm_source=preview-mode&utm_medium=rec#n631-%E6%92%B2%E5%85%8B-Poker)
:::
:::warning
[b374: [福州19中]众数](https://zerojudge.tw/ShowProblem?problemid=b374)
+ [想法參考](https://zerojudge.tw/ShowThread?postid=16300&reply=0)
:::
:::warning
[c199: 爬山去(Hiking)-TOI練習賽y7m5-1](https://zerojudge.tw/ShowProblem?problemid=c199)
+ 輸入時可先將重覆的數字去掉。
:::
:::warning
[g308: pB. 跳跳布朗尼(Brownie)](https://zerojudge.tw/ShowProblem?problemid=g308)
+ 使用布林陣列來記錄每個格子是否普經走過。
+ 亦可直接使用記錄「傳送點資訊」的陣列,走過就設為「-1」。
:::
:::warning
[n686. pA. 訊號傳遞](https://zerojudge.tw/ShowProblem?problemid=n686)
+ 依序檢查每個基地台訊號能達到的範圍,更新能達到的最遠位置。
+ [解題參考](https://hackmd.io/@cyk/2024-hgsh)
:::
:::warning
[e339: 前綴和練習](https://zerojudge.tw/ShowProblem?problemid=e339)
+ 小心不要出現pfx[-1]的狀況。
:::
### 2. list of list
+ list 中元素可以是不同型態,也可以放list。所以二維矩陣由 list of list 實作。
``` python
lst = [1,'apple',[1,2,3]]
a = [ [1, 2, 3], [4, 5, 6] ]
for i in range(2): # 列
for j in range(3): # 欄
print(a[i][j],end=' ')
print()
```
| a[0][0] | a[0][1] | a[0][2] |
| -------- | -------- | -------- |
|**a[1][0]**|**a[1][1]**|**a[1][2]**|
+ 使用列表生成式產生2維以上串列
``` python
a = [ [0 for i in range(3)] for j in range(2) ] # lst=[[0, 0, 0], [0, 0, 0]]
a = [ [0]*3 for i in range(2)] # 初始化一個2*3矩陣,初值均為 0
b = [[1,2,3]]*2 # 等於 b[0]=[1,2,3]; b[1]=b[0]。b[1][1]=5,印出 b 會看到什麼錯誤?
c = [[0]*4]*3 # c[1][1]=5,印出c會看到什麼錯誤?
```
:::info
EX_4_7:[e798: p5. 卷積神經網路](https://zerojudge.tw/ShowProblem?problemid=e798)
+ 多行輸入
``` python
a = []
for _ in range(n):
a.append([*map(int, input().split())])
a = [[] for i in range(n)]
for i in range(n):
a[i] = [*map(int, input().split())]
a = [ [*map(int, input().split())] for _ in range(n)]
```
+ 求最大值可用 max 函式或 if。
+ 小心不要存取到串列外的空間。
IndexError: list index out of range
:::
:::info
EX_4_8:[f513: 舉旗遊戲 (Flag)](https://zerojudge.tw/ShowProblem?problemid=f513)
+ m=[input().split() for _ in range( r )]
+ 如果自己的顏色和相鄰 8 點都不同,則淘汰人數+1。
+ 直接檢查每個人相鄰的 8 個點,這樣會發生什麼問題?
IndexError: list index out of range
Q:要如何改?
``` python
cnt=0
for i in range(r):
for j in range(c):
out=True # 先假設被淘汰
if m[i][j]==m[i-1][j-1]: # i>0 and j>0 and ...
out=False
if m[i][j]== m[i-1][j]:
out=False
if m[i][j]==m[i-1][j+1]: # i>0 and j<c-1 and ...
out=False
if m[i][j]==m[i][j-1]:
out=False
if m[i][j]==m[i][j+1]:
out=False
if m[i][j]==m[i+1][j-1]:
out=False
if m[i][j]==m[i+1][j]:
out=False
if m[i][j]==[i+1][j+1]:
out=False
if out:
cnt+=1
```
+ 先定義每一個方向列、欄的差值,並以for迴圈產生相鄰點的座標。
dr=[-1, -1, -1, 0, 0, 1, 1 ,1]
dc=[-1, 0, 1, -1 ,1 ,-1 ,0 ,1]
+ (進階)for ~: else:
:::
:::info
(進階)EX_4_9:[a694: 吞食天地二](https://zerojudge.tw/ShowProblem?problemid=a694)
+ 前綴和 ![](https://hackmd.io/_uploads/r1vpzDlSn.png) **➜** ![](https://hackmd.io/_uploads/BJMRGvlr3.png)
+ [如何以a693的方式加速?](https://sites.google.com/a/mail.hpsh.tp.edu.tw/pc/jiao-cai/a694-tun-shi-tian-de-er)
|[0][0] |[0][1]|[0][2] |[0][3] |[0][4]|[0][5] |
|:----: |:----:|:----: |:----: |:----:|:----: |
|**[1][0]**| | | | | |
|**[2][0]**| |[r1-1][c1-1]| | |[r1-1][c2]|
|**[3][0]**| | |[r1][c1]| | |
|**[4][0]**| | | | | |
|**[5][0]**| |[r2][c1-1] | | |[r2][c2] |
:::
:::warning
[o077. 2. 電子畫布](https://zerojudge.tw/ShowProblem?problemid=o077)
+ a=[[0]\*w for i in range(h)] # 初始化一個h*w矩陣,初值均為 0
+ 遍歷陣列所有點,如果此點跟座標(r,c)距離在 t 內就把那點+=x
+ 印出陣列
``` python
for row in a: # 取出每一列
print(*row) # 印出此列的每個元素,以空白隔開
```
:::
:::warning
[b367: 翻轉世界](https://zerojudge.tw/ShowProblem?problemid=b367)
+ 假設 a180 為 a 轉 180 度後的陣列,a[i][j] 轉180度後會放在 a180[r-i-1][c-j-1];
+ [題意轉180度的意思](https://zerojudge.tw/ShowThread?postid=21462&reply=9472#21462)
:::
:::warning
[f418: Word Search Puzzle](https://zerojudge.tw/ShowProblem?problemid=f418)
+ 不會有起始點在下,終點在上面的單字。
+ 總共只有3種情況
- r1==r2 橫著印
- c1==c2 直著印
- 其它斜著印,從(r1+1,c1+1),(r1+2,c1+2)......印到(r1+(r2-r1-1),c1+(c2-c1-1)),(r2,c2)
+ [解題參考](https://www.youtube.com/watch?v=BDHhgndIP-s)
:::
:::warning
[e787: b2.尋寶地圖(Map)](https://zerojudge.tw/ShowProblem?problemid=e787)
+ 轉換圖計算行、列和時,重複算的要扣除。
+ [題目](https://tpmso.org/toi/wp-content/uploads/question/201912/B2-Map.pdf)
+ [解題參考(1)](https://tpmso.org/toi/wp-content/uploads/question/201912/B2-Map.pptx)、[(2)](https://www.youtube.com/watch?v=lGYJUGmPzCk)
+ 兩張地圖資料之間有一個空白行。
:::
## 五、字串
### 1. 字串相關操作
+ 與 list 操作類似,相加是串接,乘整數是重複。
+ 字串與 list 一樣可以 slice,但字串內容不可更改。
``` python
s = 'Hello World'
s[1]
s[1] = 'x' # error
a = s[0:5]*2
a = s[:4]+' Python '+s[6:]
a = s[::-1] # 反轉字串
```
+ 字串與 list 都可以用 in 檢查元素(字元、子字串)是否在裏面。
``` python
s = 'Hello World'
'H' in s
'E' in s # False
'He' in s
'She' in s # False
```
### 2. 字串(string)相關函式
+ [Python 字串操作(string替換、刪除、擷取、複製、連線、比較、查詢、包含、大小寫轉換、分割等)](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/358746/)
+ [RUNOOB Python 字符串](http://www.runoob.com/python/python-strings.html)
| 字串相關函式 | 意義 |
|:----------------|:------ |
| str(n) |將變數n轉為字串型態|
| len(s) |計算變數s的長度|
| str.lower() |將字串中的字母轉成小寫|
| str.upper() |將字串中的字母轉成大寫|
| str.islower() |判斷字串中的字母是否皆為小寫|
| str.isupper() |判斷字串中的字母是否皆為大寫|
| str.find('abc') |尋找字串中'abc'的位置|
| str.count('abc')|計算字串中'abc'出現的次數|
| str.replace(舊子字串,新子字串)|將字串中的舊子字串用新子字串取代|
| str.split()|將字串分割成數個子字串(以空白區分)|
| str.strip()|去掉字串左右空白|
| str.join(sequence)| 指定字符(str)連接串列(sequence)中的元素後,生成新字串 |
| 'ab' in 'abcd' | 判斷'ab'是否在'abcd' |
| str[::-1] | 將字串反轉 |
| [] | 操作同list |
:::info
EX_5_1:[b428: 凱薩加密](https://zerojudge.tw/ShowProblem?problemid=b428)
+ ord(): 字元的 ASCII code
+ chr(): ASCII 轉字元
+ if 或 %
+ Q:可以寫b[1]-a[1]嗎?
:::
:::info
EX_5_2:[d235: Q10929:You can say 11](https://zerojudge.tw/ShowProblem?problemid=d235)
+ 11的倍數判別法:奇數位數字和與偶數位數字和相差為11的倍數。
+ [1~13的倍數判別法](https://leestar2013.pixnet.net/blog/post/45638266)
+ 使用列表生成式收進奇、偶項。
:::
:::info
EX_5_3:[h083: 3. 數位占卜](https://zerojudge.tw/ShowProblem?problemid=h083)
+ 先用暴力法 $\rightarrow$ NA (score:20%)
+ [100%解題參考](https://www.youtube.com/watch?v=VNSmO1y1W-w
)
:::
:::warning
[a009: 解碼器](https://zerojudge.tw/ShowProblem?problemid=a009)
+ 字串遍歷
``` python
str=input()
for a in str:
print(a)
```
:::
:::warning
[a065: 提款卡密碼](https://zerojudge.tw/ShowProblem?problemid=a065)
:::
:::warning
[d124: 3的倍数](https://zerojudge.tw/ShowProblem?problemid=d124)
+ 3的倍數判別法:各個數字和為3的倍數。
+ 負號要忽略。
:::
:::warning
[b516: 凱撒密碼-商競103](https://zerojudge.tw/ShowProblem?problemid=b516)
:::
:::warning
[e505: 12602 - Nice Licence Plates](https://zerojudge.tw/ShowProblem?problemid=e505)
+ 取絕對值函式:abs()
:::
:::warning
[g006: 密碼備忘錄 (Password)](https://zerojudge.tw/ShowProblem?problemid=g006)
+ 以陣列儲存字母出現的次數,cnt[ord(ch)-65]+=1。
+ 因為最多100個字母,表示次數最大為100,由100->1檢查陣列中是否有這個次數,如果有則輸出 print(chr(i+65), end='')
+ [解題參考](https://tpmso.org/toi/wp-content/uploads/question/202105/Password.odp)
:::
:::warning
[c276: 沒有手機的下課時間](https://zerojudge.tw/ShowProblem?problemid=c276)
:::
## 六、函式(遞迴)
### 1. 自定函式宣告語法
``` python
def 函式名稱([參數1, 參數2, ....]):
程式碼
[return 回傳值1, 回傳值2, ....] # 函數可以同時返回多個值(一個tuple)
```
``` python
def 函式名稱([參數1=預設值, 參數2, ....]):
程式碼
[return 回傳值1, 回傳值2, ....] # 函數可以同時返回多個值(一個tuple)
```
``` python
def 函式名稱(*參數): # 參數數量不定,以tuple儲存
程式碼
[return 回傳值1, 回傳值2, ....]
```
:::info
EX_6_1:[a623: 3. Combination](https://zerojudge.tw/ShowProblem?problemid=a623)
+ 將n!寫成函式,在主程式呼叫3次。
+ $C(n,k)=\frac{n!}{(n-k)! * k!}$,例如C(4,2)=6。
``` python
def ~
~
return ~
while True:
try:
~
~
except:
break
```
:::
:::warning
[f327: 刪除欄位](https://zerojudge.tw/ShowProblem?problemid=f327)。
+ 寫一函式將輸入的字串轉成整數(26進位),A為1,B為2,…,AA為27,AA為28,…。
``` python
for ch in s:
n=n*26+ord(ch)-64
```
:::
:::warning
[b112: 5. 高中運動會](https://zerojudge.tw/ShowProblem?problemid=b112)。
+ 寫一函式求兩數的最大公因數(輾轉相除法)。
+ a=b*q+r → gcd(a,b)=gcd(b,r)
:::
### 2. 遞迴
+ 在函式之中呼叫函式自己本身(數學上為函數自己定義自己)
+ 問題的答案,可從同類的子問題(規模更小)得到。
+ 要有終止條件,不然會無窮遞迴下去。
:::info
EX_6_2:[95數學學測填充題G](http://cs.cysh.cy.edu.tw/computer_concept_108/高中數學遞迴.pdf)
用黑、白兩種顏色的正方形地磚依照如下的規律拼成若干圖形:
![](https://i.imgur.com/PrDcedl.jpg)
拼第95個圖需用到幾塊白色地磚。(478)
:::
``` python=
def f(n):
if ~:
~
else:
return ~
n=int(input())
print(f(n)) # 5->28
```
:::info
EX_6_3:[a024. 最大公因數(GCD)](https://zerojudge.tw/ShowProblem?problemid=a024)
+ [原理](https://www.youtube.com/watch?v=fGesPF3QA1U)
+ a=b*q+r → gcd(a,b)=gcd(b,r)
:::
:::warning
[e357: 遞迴函數練習](https://zerojudge.tw/ShowProblem?problemid=e357)
:::
:::warning
[c002: 10696 - f91](https://zerojudge.tw/ShowProblem?problemid=c002)
:::
### 3. 區域變數 vs. 全域變數
- 在函式中的變數為區域變數,在函式外的變數為全域變數。
``` python=
def fun():
a = 10 # 此處的 a 為區域變數
print('函式內', a)
a = 5 # 此處的 a 為全域變數
fun()
print('主程式', a) # a 印出5
```
``` python=
def fun():
global a # 使用全域變數 a
a = 10
print('函式內', a)
a = 5 # 此處的 a 為全域變數
fun()
print('主程式', a) # a 被函式改變,印出 10
```
``` python=
def fun():
print('函式內', a) # 可以使用全域變數 a,印出 5
a = 5 # 此處的 a 為全域變數
fun()
```
```python=
def fun(a): # 更改參數 a 不會影響函式外的變數
a = 10
print('函式內', a)
a = 5
fun(a)
print('主程式', a)
```