###### 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,...\]) - 字串要加 '&nbsp;&nbsp;' 或 "&nbsp;&nbsp;" - 可用 + 將字串連接 - 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) + 字串型態:'&nbsp;&nbsp;' 或 "&nbsp;&nbsp;" 中的文字 + 容器型態: - 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) ```