W07|把資料再拿出來用:一維串列的多輪走訪
今天完成後,我可以
- 先保存整批資料,算出需要的資訊後,再由左到右走訪同一個串列。
- 分清楚索引
i與串列內容L[i],依保存方式判斷題目編號。 - 分清原始數值與調整後的數值,用正確的資料完成統計。
本週沿用W06的固定長度串列與索引寫法,重點是再次使用已保存的資料。
課中配分:
b033、b034各50分。課後配分:a379、a387各30分,a38840分。
一、課中練習
1-1|b033 在平均之上(教師示範,50分)
題目先輸入全班成績,最後要回答有多少人成績大於等於全班平均。教師示範時,請一邊在自己的電腦操作,一邊觀察:
- 輸入第一筆成績時,能知道全班平均嗎?
- 如果沿用W04邊輸入邊計算、不把成績存進
L,等全班平均算出後會遇到什麼問題? - 平均算出後,為什麼要再走訪一次
L? - 迴圈中的
i與L[i],哪一個是成績?
這題延續W06的b023串列版:先保存成績並算平均,再增加一輪統計。成績可以自行決定放在L的第0~n - 1格,或第1~n格;選定後,每一輪的範圍都要一致。
需要時展開:再次走訪的骨架
完成後整理:不知道錯在哪裡時分段檢查
可以暫時在三個位置加入輸出:
確認後要刪除多餘輸出再提交。
1-2|b034 平均之上的平均(獨立練習,50分)
這題沿用b033保存的成績與算出的全班平均,改求「平均以上同學」的平均成績。先用少量資料手算,再寫出你的處理方式。
開始前先回答:
- 若成績是
50、70、90,全班平均是70,新平均應根據哪幾筆成績? - 手算新平均時,分子和分母各代表什麼?
需要時展開:手算與程式選到相同資料嗎?
用上面的三筆成績,先在紙上圈出應納入新平均的資料,再對照程式實際納入哪幾筆。若選到的資料相同而結果不同,檢查你用什麼數字當分子和分母。
二、解題後整理:Top Down 思考,Bottom Up 實作
- Top Down 思考: 把
b034最後要輸出的「平均以上同學的平均」寫在最上方。要算出它,得先知道什麼?把需要的資訊寫在下方、用箭頭連起來,再繼續往下拆,直到接上題目給的資料。 - Bottom Up 實作: 沿著這張圖由下往上做。先完成不再依賴其他結果的部分,再用已完成的結果算出上一層,直到得到最後的輸出。
回看b033與b034:兩題有哪些資訊可以共用?最後要的結果不同,程式的哪一部分因此改變?
三、課後挑戰
先到JMJ依題號閱讀完整題目與範例。第一題延伸課中的多輪走訪;第二題要依條件分階段輸出,第三題要對照同一人的兩種資料。
| 題目 | 本週目標 |
|---|---|
a379 加分後的飲料 |
找出最低分,統計調分後超過100分的人數 |
a387 出遊分帳 |
先輸出所有補款動作,再輸出所有領款動作 |
a388 敗部復活賽 |
對照評審分數與人氣票數,選出復活者 |
3-1|a379 加分後的飲料
沿用W06的方式,逐筆讀入原始成績並存進L。如果邊輸入邊判斷誰有飲料,當下還缺少哪個資訊?
你可以自行決定是否更新L中的分數;題目要求的是需要準備的飲料杯數。
開始寫程式前,先用自己選的兩三筆成績手算共同加分、調整後的分數與飲料杯數,再用這組資料檢查程式。
需要時展開:最低分為什麼變成 0?
用原始成績50、80檢查:最低分應是50。如果程式得到0,檢查「目前最低分」是不是一開始就設成0,而沒有取自真正輸入的一筆成績。若你保留L[0]不放成績,也確認沒有把那格算進去。
3-2|a387 出遊分帳
先看JMJ題目與範例。每人應分攤多少錢,要等哪個數值算出後才能確定?為了稍後依編號處理每個人的動作,輸入時哪些資料需要留下?
需要時展開:整數分攤額與輸出順序
先用範例逐人算出已代墊金額與應分攤金額的差,分清楚誰要補款、誰要領款。
Python 用 // 做除法並向下取整,例如 7 // 2 得到 3;用 / 則得到 3.5。本題保證總費用能被人數整除,算每人分攤額時可以用 //。
題目要求所有補款動作先出現,所有領款動作後出現。可以用第一個for迴圈只輸出補款動作,再用第二個for迴圈只輸出領款動作;兩輪都依編號由小到大走訪。
需要時展開:一行輸出文字、編號與金額
number和money是示意名稱,寫程式時要換成題目編號與這次動作的金額。print()會在逗號分隔的項目之間自動印出空白,並在這行結束後換行;領款時把"PAY"改成"GET"。題目編號是1到n,請留意它與自己使用的串列索引是否相同。
3-3|a388 敗部復活賽
先看JMJ題目與範例。第一位參賽者的分數輸入時,直接晉級的門檻已經知道了嗎?如果還不知道,之後要怎麼找回這位參賽者的資料?
需要時展開:一行讀入兩個數字
split()切開後的兩份資料仍是文字,存進去前記得用int()轉成整數。
需要時展開:兩種資料怎麼保存?
讀完所有人之後,你還找得到第2位的人氣票數嗎?串列的每一格只能放一個數字。兩種資料要怎麼保存,才能用同一個i找回同一個人的評審分數和人氣票數?
需要時展開:整數平均與復活資格
評審平均要無條件捨去至整數時,可以用 //:7 // 2 得到 3,而 7 / 2 得到 3.5。本題分數都是非負整數,// 符合這裡的取整數規則。
先用範例圈出直接晉級者,再看看程式考慮復活者時,是否只比較未直接晉級者的人氣票數。若票數相同,請核對選出的編號。
完成後挑戰:把讀入縮成一行
這是完成題目後的選學延伸,看懂、會用即可,不要求改寫已完成的程式。
- W06
a066的提示看過month, day = map(int, input().split())。它和先split()、再分別用int()轉型的寫法差在哪裡?改用它,讀入時可以少掉哪幾行? - W06學過
L[i] = 值會直接把值寫進串列的某一格。等號左邊的兩個變數,能不能直接換成你要寫入的那兩格? - 改完後,在輸入迴圈結束時暫時印出你的兩個串列,確認每格都是整數。如果少了
map(int, …),存進去的會是什麼?比較人氣票數時會出什麼問題?試比較"90"和"100"。
四、完成後自我檢查
- 我能說明為什麼要先保存全部資料,再從頭走訪。
- 我能讓每一輪的範圍與
L的保存方式一致。 - 我知道
i是位置、L[i]是內容;第一筆存在索引0時,題目編號是i + 1。 - 我能在找出平均、最大值或最小值後,重新走訪資料完成統計。
- 我能用調分後的成績判斷是否超過
100分,不把原始分數誤當成新分數。 - 我能依題目要求分階段輸出資料,不把不同動作交錯印出。
- 我能用同一個索引對照一個人的兩種資料,再依條件選出要比較的對象。
