Example 5 — Find the Vote Winner (debugging) ตัวอย่างที่ 5 — หาผู้ชนะการโหวต (debugging)

A debugging problem: the program below should count the votes and name the winner, but it hides one bug. โจทย์ debugging: โปรแกรมด้านล่างควรนับคะแนนโหวตแล้วบอกผู้ชนะ แต่มี bug ซ่อนอยู่ 1 จุด

How to work on this page: read the problem and the flowcharts, then check the code against the flowcharts box by box. Run the test list, find the wrong line, and fix the program in the code box yourself. Run the test list again until every test gives its expected output, and only then open the solution. To review the kinds of error, the kinds of test case and the bug-hunting tools, see 11 Testing and Debugging.

วิธีทำโจทย์หน้านี้: อ่านโจทย์และ flowchart แล้วตรวจโค้ดเทียบกับ flowchart ทีละกล่อง จากนั้นรันตามรายการทดสอบ หาบรรทัดที่ผิด และแก้โปรแกรมในกล่องโค้ดเอง รันรายการทดสอบซ้ำจนทุกข้อได้ผลตามที่ควรได้ แล้วจึงเปิดดูเฉลย ทบทวนชนิดของ error, ชนิดของ test case และเครื่องมือหา bug ได้ที่บท 11 การทดสอบและการแก้ไขโปรแกรม

1 The problem โจทย์

A club is choosing its president. Each candidate has a code of one capital letter (A to E), and each ballot carries one code. The vote counter types the codes of all the ballots as one piece of text with no spaces (at least 1 ballot). The program must show the winner and the number of votes the winner got. If several candidates share the most votes, the winner is the one whose code appears first in the typed text.

ชมรมแห่งหนึ่งกำลังเลือกประธาน ผู้สมัครแต่ละคนมีรหัสเป็นอักษรตัวใหญ่ 1 ตัว (A ถึง E) และบัตรโหวต 1 ใบมีรหัส 1 ตัว ผู้นับคะแนนพิมพ์รหัสจากบัตรโหวตทุกใบต่อกันเป็นข้อความเดียวโดยไม่เว้นวรรค (อย่างน้อย 1 ใบ) โปรแกรมต้องแสดงผู้ชนะและจำนวนคะแนนโหวตที่ผู้ชนะได้ ถ้ามีผู้สมัครหลายคนได้คะแนนสูงสุดเท่ากัน ผู้ชนะคือคนที่รหัสปรากฏในข้อความที่พิมพ์ก่อน

  • Example: BACBB → Winner: B and Votes: 3
  • count_votes(ballots) — returns a dictionary that holds how many votes each candidate got
  • find_winner(tally) — returns the code of the winner
  • ตัวอย่าง: BACBB → Winner: B และ Votes: 3
  • count_votes(ballots) — คืน dictionary ที่เก็บว่าผู้สมัครแต่ละคนได้คะแนนโหวตกี่คะแนน
  • find_winner(tally) — คืนรหัสของผู้ชนะ

New in this program: tally = {} creates an empty dictionary; vote not in tally is true when vote is not a key of tally yet; tally[vote] = 0 adds the key vote with the value 0; tally[vote] += 1 adds 1 to the value of that key. for name in tally visits the keys in the order they were added, which is the order in which the codes first appear in the text. Because find_winner uses >, a later candidate with the same number of votes does not replace the one found first (with >= it would).

คำสั่งใหม่ในโปรแกรมนี้: tally = {} สร้าง dictionary ว่าง vote not in tally เป็นจริงเมื่อ vote ยังไม่เป็น key ของ tally ส่วน tally[vote] = 0 เพิ่ม key vote ที่มี value เป็น 0 และ tally[vote] += 1 เพิ่ม value ของ key นั้นขึ้น 1 คำสั่ง for name in tally ไล่ key ตามลำดับที่ถูกเพิ่มเข้าไป ซึ่งก็คือลำดับที่รหัสปรากฏครั้งแรกในข้อความ และเพราะ find_winner ใช้ > ผู้สมัครที่มาทีหลังแต่ได้คะแนนเท่ากัน จึงไม่แทนที่คนที่พบก่อน (ถ้าใช้ >= จะแทนที่)

2 Main program — flowchart and full code (contains a bug) โปรแกรมหลัก — flowchart และโค้ดทั้งหมด (มี bug)

The program starts by reading the typed codes into ballots. Next it counts the votes with the sub-function count_votes and stores the dictionary in tally. Then it finds the winner with the sub-function find_winner and stores it in winner. It shows the winner and the winner's votes, tally[winner], with print, and the program ends.

โปรแกรมนี้เริ่มต้นด้วยรับรหัสที่ผู้ใช้พิมพ์เก็บใน ballots ถัดไปนับคะแนนโหวตด้วย function ย่อยชื่อ count_votes แล้วเก็บ dictionary ที่ได้ใน tally หลังจากนั้นหาผู้ชนะด้วย function ย่อยชื่อ find_winner แล้วเก็บใน winner แสดงผู้ชนะและคะแนนโหวตของผู้ชนะ tally[winner] ด้วย print และจบการทำงานของโปรแกรม

Start Read the ballots ballots = input(...) Count the votes tally = count_votes(ballots) Find the winner winner = find_winner(tally) Show the winner print("Winner:", winner) Show the winner's votes print("Votes:", tally[winner]) End
[main]
[input]
[output]
Enter the ballots: BACBB
Winner: B
Votes: 1

Try it yourself — type the ballot codes with no spaces and press Submit. They replace the [input] box and run the code that is in the box right now (including your fix). Press Submit with an empty box to test an empty input.

ลองป้อนค่าเอง — พิมพ์รหัสจากบัตรโหวตต่อกันโดยไม่เว้นวรรคแล้วกดส่ง ค่าจะแทนที่กล่อง [input] แล้วรันโค้ดที่อยู่ในกล่องตอนนี้ (รวมถึงส่วนที่คุณแก้แล้ว) ถ้าต้องการทดสอบข้อมูลว่าง ให้กดส่งโดยไม่พิมพ์อะไร

3 count_votes(ballots)

count_votes starts by creating an empty dictionary tally. It checks whether there is another ballot in ballots; if there is, it takes its code as vote and checks whether vote not in tally. If it is, it adds the candidate with tally[vote] = 0, then adds one vote with tally[vote] += 1, and goes back to check for another ballot. If it is not, it goes straight back to check for another ballot. This repeats until there are no ballots left, so it sends tally back with return.

count_votes เริ่มต้นด้วยสร้าง dictionary ว่างชื่อ tally แล้วตรวจสอบว่ายังมีบัตรโหวตใน ballots เหลืออยู่หรือไม่ ถ้าใช่ให้นำรหัสของบัตรใบนั้นเป็น vote แล้วตรวจสอบเงื่อนไขว่า vote not in tally หรือไม่ ถ้าใช่ให้เพิ่มผู้สมัครด้วย tally[vote] = 0 แล้วเพิ่มคะแนน 1 คะแนนด้วย tally[vote] += 1 และกลับไปตรวจสอบว่ายังมีบัตรโหวตเหลือหรือไม่ ถ้าไม่ใช่ให้กลับไปตรวจสอบทันที ทำแบบนี้จนไม่มีบัตรโหวตเหลือ จึงส่งค่า tally กลับด้วย return

count_votes(ballots) Start an empty dictionary tally = {} count each ballot More ballots? for vote in ballots Yes New candidate? vote not in tally? Yes Add the candidate tally[vote] = 0 Add one vote tally[vote] += 1 No No return tally

Test the function on its own: it should give a dictionary of votes.

ทดสอบฟังก์ชันนี้แยกเดี่ยวๆ ควรได้ dictionary ของคะแนนโหวต

[test]
[output]
{'B': 1, 'A': 1, 'C': 1}
{'D': 1}
4 find_winner(tally)

find_winner starts by setting winner = "" to hold the answer and most = 0 as the most votes found so far. It checks whether there is another candidate in tally; if there is, it takes its code as name and checks whether tally[name] > most. If it is, it stores winner = name and most = tally[name]. Either way it goes back to check for another candidate. This repeats until there are no candidates left, so it sends winner back with return.

find_winner เริ่มต้นด้วยกำหนดค่า winner = "" สำหรับเก็บคำตอบ และ most = 0 เป็นคะแนนโหวตที่มากที่สุดที่พบจนถึงตอนนี้ แล้วตรวจสอบว่ายังมีผู้สมัครใน tally เหลืออยู่หรือไม่ ถ้าใช่ให้นำรหัสของผู้สมัครคนนั้นเป็น name แล้วตรวจสอบเงื่อนไขว่า tally[name] > most หรือไม่ ถ้าใช่ให้เก็บ winner = name และ most = tally[name] ไม่ว่าทางใดทางหนึ่ง หลังจากนั้นกลับไปตรวจสอบว่ายังมีผู้สมัครเหลือหรือไม่ ทำแบบนี้จนไม่มีผู้สมัครเหลือ จึงส่งค่า winner กลับด้วย return

find_winner(tally) No winner yet winner = "" most = 0 check each candidate More candidates? for name in tally Yes Beats the best? tally[name] > most? Yes Remember this candidate winner = name most = tally[name] No No return winner

Test the function on its own with dictionaries of votes (no typing needed).

ทดสอบฟังก์ชันนี้แยกเดี่ยวๆ ด้วย dictionary ของคะแนนโหวต (ไม่ต้องพิมพ์ค่า)

[test]
[output]
B
E
5 Test list รายการทดสอบ

Run each input yourself (type it into the form in card 2) and compare the result with the expected output column. The last column shows what the code with the bug gives.

รันทีละข้อด้วยตัวเอง (พิมพ์ลงในช่องของการ์ดที่ 2) แล้วเทียบผลกับคอลัมน์ผลที่ควรได้ คอลัมน์สุดท้ายคือผลจากโค้ดที่ยังมี bug

Inputข้อมูลที่ป้อน Kindชนิด Expected outputผลที่ควรได้ Output of the buggy codeผลจากโค้ดที่มี bug
BACBB Normal Winner: B
Votes: 3
Winner: B
Votes: 1 ✗
CABAD Normal Winner: A
Votes: 2
Winner: C
Votes: 1 ✗
D Boundary (1 ballot)Boundary (บัตรโหวต 1 ใบ) Winner: D
Votes: 1
Winner: D
Votes: 1 ✓
EEEE Boundary (every ballot for one candidate)Boundary (ทุกใบเลือกผู้สมัครคนเดียวกัน) Winner: E
Votes: 4
Winner: E
Votes: 1 ✗
ABCDE Boundary (every ballot different)Boundary (ทุกใบเลือกคนละคน) Winner: A
Votes: 1
Winner: A
Votes: 1 ✓
ABBA Boundary (a tie → the one that appears first)Boundary (คะแนนเท่ากัน → ตอบคนที่ปรากฏก่อน) Winner: A
Votes: 2
Winner: A
Votes: 1 ✗
(empty)(ว่าง) Error (no ballots)Error (ไม่มีบัตรโหวต) should be rejected, but this program does not check its input ควรถูกปฏิเสธ แต่โปรแกรมนี้ไม่ได้ตรวจข้อมูลที่รับเข้ามา Winner:
KeyError: ''
6 Your tasks ภารกิจ
  1. Check the code of both functions and the main program against their flowcharts, box by box, and check each flowchart against the problem.
  2. Run every input in the test list and note whether the actual output matches the expected output.
  3. Why do D and ABCDE pass? What do you notice about Votes: in every failing test, and about the winner the buggy code picks?
  4. Which kind of error is this bug, and why?
  5. Add print(vote, tally) as the last line inside the loop of count_votes (lined up with if) and fill in the trace table below for BAB.
  6. Fix the code in the box and run the test list again. Every Normal and Boundary input must give its expected output.
  7. Think further: how could find_winner be changed to show every candidate who shares the most votes? And how should the program deal with an empty input?
  1. ตรวจโค้ดของทั้ง 2 ฟังก์ชันและโปรแกรมหลักเทียบกับ flowchart ทีละกล่อง และตรวจ flowchart แต่ละอันเทียบกับโจทย์
  2. รันทุกข้อในรายการทดสอบ แล้วจดผลที่ได้จริงว่าตรงกับผลที่ควรได้หรือไม่
  3. ทำไม D และ ABCDE ผ่าน ข้อที่ไม่ผ่านทุกข้อมีอะไรเหมือนกันที่ Votes: และผู้ชนะที่โค้ดที่มี bug เลือกเป็นใคร
  4. bug นี้เป็น error ชนิดไหน เพราะอะไร
  5. ใส่ print(vote, tally) เป็นบรรทัดสุดท้ายใน loop ของ count_votes (ย่อหน้าตรงกับ if) แล้วกรอก trace table ด้านล่างของ BAB
  6. แก้โค้ดในกล่อง แล้วรันรายการทดสอบซ้ำ ข้อที่เป็น Normal และ Boundary ต้องได้ผลตามตารางทุกข้อ
  7. ชวนคิดต่อ: ถ้าต้องการให้แสดงทุกคนที่ได้คะแนนสูงสุดเท่ากัน จะแก้ find_winner อย่างไร และโปรแกรมควรจัดการกับข้อมูลว่างอย่างไร
Trace table: count_votes("BAB") trace table: count_votes("BAB")
Roundรอบvotevote not in tally?tally at the end of the roundtally หลังจบรอบ
1   
2   
3   
7 Solution เฉลย
Show the fixed code ดูโค้ดที่แก้แล้ว

The bug is the indentation of the line tally[vote] += 1. It sits inside if vote not in tally:, so it runs only the first time each candidate appears, and every candidate ends with 1 vote. In the flowchart the box "Add one vote" is on the Yes path only, but the problem needs one vote for every ballot. Move the line 4 spaces to the left so that it lines up with if; then it runs once for every ballot. It is a logic error: the indentation is still valid Python, so the program runs to the end with no error message. D and ABCDE hide the bug, because there every candidate really has 1 vote. And because every count is 1, find_winner always picks the first ballot: that is why BACBB still names the right winner but shows the wrong number of votes.

bug อยู่ที่การย่อหน้าของบรรทัด tally[vote] += 1 บรรทัดนี้อยู่ใน if vote not in tally: จึงทำงานเฉพาะครั้งแรกที่ผู้สมัครแต่ละคนปรากฏ ผู้สมัครทุกคนจึงได้ 1 คะแนนเสมอ ใน flowchart กล่อง "Add one vote" อยู่บนทาง Yes เท่านั้น แต่โจทย์ต้องการเพิ่ม 1 คะแนนให้บัตรโหวตทุกใบ แก้โดยเลื่อนบรรทัดนี้ไปทางซ้าย 4 ช่องให้ตรงกับ if บรรทัดนี้จึงทำงานทุกครั้งที่อ่านบัตรโหวต 1 ใบ เป็น logic error เพราะการย่อหน้าแบบนี้ยังเป็น Python ที่ถูกต้อง โปรแกรมจึงรันจบโดยไม่มีข้อความ error ส่วน D และ ABCDE ซ่อน bug ไว้ เพราะผู้สมัครทุกคนได้ 1 คะแนนจริงๆ และเมื่อทุกคนได้ 1 คะแนน find_winner จึงเลือกบัตรโหวตใบแรกเสมอ BACBB จึงยังบอกผู้ชนะถูก แต่จำนวนคะแนนโหวตผิด

Trace table of the buggy code: count_votes("BAB") trace table ของโค้ดที่มี bug: count_votes("BAB")
Roundรอบvotevote not in tally?tally at the end of the roundtally หลังจบรอบ
1B✓{'B': 1}
2A✓{'B': 1, 'A': 1}
3B✗{'B': 1, 'A': 1}

After the fix, round 3 gives {'B': 2, 'A': 1}.

หลังแก้แล้ว รอบที่ 3 จะได้ {'B': 2, 'A': 1}

[fixed]
[input]
[output]
Enter the ballots: BACBB
Winner: B
Votes: 3

The Run buttons on this page simulate Python with JavaScript, the same as the other lessons. To run the real Python, paste the code into Google Colab.

ปุ่ม Run ในหน้านี้จำลองโค้ด Python ด้วย JavaScript เหมือนบทเรียนอื่นๆ หากต้องการรัน Python จริง ให้คัดลอกโค้ดไปวางที่ Google Colab

References References / แหล่งอ้างอิง

  1. Python docs — Tutorial: Dictionaries (keys, in / not in, and looping over a dictionary in the order the keys were added) (key, in / not in และการวน loop บน dictionary ตามลำดับที่เพิ่ม key)
  2. Python docs — Lexical analysis: Indentation (how indentation decides which block a line belongs to) (การย่อหน้าบอกว่าบรรทัดนั้นอยู่ใน block ไหน)
  3. Kinds of error, kinds of test case and bug-hunting tools: 11 Testing and Debugging; dictionaries: 08 Dictionary; flowchart symbols: 01 Basic → Flowchart Basic. ชนิดของ error, ชนิดของ test case และเครื่องมือหา bug: 11 การทดสอบและการแก้ไขโปรแกรม ; dictionary: 08 Dictionary ; สัญลักษณ์ของ flowchart: 01 Basic → Flowchart Basic

End-of-lesson quizแบบฝึกหัดท้ายบท

ตอบแล้ว 0 / 10

ข้อ 1

1 / 10

When count_votes meets a candidate for the first time, what does tally[vote] = 0 do?เมื่อ count_votes พบผู้สมัครคนหนึ่งเป็นครั้งแรก บรรทัด tally[vote] = 0 ทำอะไร?

เฉลย / Answerซ่อนเฉลย / Hide

เฉลย / Answer: (B) It adds the key vote with the value 0 to tallyเพิ่ม key vote ที่มี value เป็น 0 เข้าไปใน tally

คำอธิบายแต่ละตัวเลือก / Explanation for each choice

  • (A) It removes the candidate from tallyลบผู้สมัครคนนั้นออกจาก tally
    Wrong: assigning with = does not remove a key.ผิด: การกำหนดค่าด้วย = ไม่ได้ลบ key
  • (B) It adds the key vote with the value 0 to tallyเพิ่ม key vote ที่มี value เป็น 0 เข้าไปใน tally
    Correct! The key is not there yet, so the assignment adds a new key with the value 0.ถูกต้อง! key ยังไม่มีอยู่ การกำหนดค่าจึงเพิ่ม key ใหม่ที่มี value เป็น 0
  • (C) It sets the value of every candidate to 0ทำให้ value ของผู้สมัครทุกคนเป็น 0
    Wrong: the line changes only the key vote.ผิด: บรรทัดนี้เปลี่ยนเฉพาะ key vote เท่านั้น
  • (D) It raises KeyError because the key is not there yetเกิด KeyError เพราะ key ยังไม่มีอยู่
    Wrong: KeyError comes from reading a missing key; assigning to a new key is fine.ผิด: KeyError เกิดเมื่ออ่าน key ที่ไม่มี แต่การกำหนดค่าให้ key ใหม่ทำได้

ข้อ 2

2 / 10

Which kind of error is the bug in this program?bug ในโปรแกรมนี้เป็น error ชนิดใด?

เฉลย / Answerซ่อนเฉลย / Hide

เฉลย / Answer: (D) A logic errorlogic error

คำอธิบายแต่ละตัวเลือก / Explanation for each choice

  • (A) A syntax errorsyntax error
    Wrong: the code follows the grammar of Python, so the program starts to run.ผิด: โค้ดถูกหลักไวยากรณ์ โปรแกรมจึงเริ่มรันได้
  • (B) A run-time errorrun-time error
    Wrong: a normal input such as BACBB runs to the end with no error message.ผิด: ข้อมูลปกติอย่าง BACBB รันจบโดยไม่มีข้อความ error
  • (C) IndentationErrorIndentationError
    Wrong: the wrong indentation in this problem is still valid Python, so there is no IndentationError.ผิด: การย่อหน้าที่ผิดในโจทย์นี้ยังเป็น Python ที่ถูกต้อง จึงไม่มี IndentationError
  • (D) A logic errorlogic error
    Correct! The program runs to the end, but the number of votes it shows is wrong.ถูกต้อง! โปรแกรมรันจบ แต่จำนวนคะแนนโหวตที่แสดงผิด

ข้อ 3

3 / 10

Why does the test D pass even though the program has a bug?ทำไม test D จึงผ่านทั้งที่โปรแกรมมี bug?

เฉลย / Answerซ่อนเฉลย / Hide

เฉลย / Answer: (A) There is only one ballot, so the right count is 1, which the buggy code also givesมีบัตรโหวตใบเดียว คะแนนที่ถูกต้องคือ 1 ซึ่งโค้ดที่มี bug ก็ได้ 1 เช่นกัน

คำอธิบายแต่ละตัวเลือก / Explanation for each choice

  • (A) There is only one ballot, so the right count is 1, which the buggy code also givesมีบัตรโหวตใบเดียว คะแนนที่ถูกต้องคือ 1 ซึ่งโค้ดที่มี bug ก็ได้ 1 เช่นกัน
    Correct! The bug gives every candidate 1 vote, which happens to be the right answer when there is one ballot.ถูกต้อง! bug ทำให้ทุกคนได้ 1 คะแนน ซึ่งตรงกับคำตอบจริงพอดีเมื่อมีบัตรโหวตใบเดียว
  • (B) Because D comes late in A to Eเพราะ D อยู่ท้ายตัวอักษร A ถึง E
    Wrong: the program does not sort or compare letters.ผิด: โปรแกรมไม่ได้เรียงหรือเทียบลำดับตัวอักษร
  • (C) Because find_winner skips the first candidateเพราะ find_winner ข้ามผู้สมัครคนแรก
    Wrong: find_winner checks every candidate, and the answer is D.ผิด: find_winner ตรวจผู้สมัครทุกคน และผลก็คือ D
  • (D) Because an input of one letter does not enter the loopเพราะข้อมูลที่มีตัวเดียวไม่เข้า loop
    Wrong: the loop runs once for the one ballot.ผิด: loop ทำงาน 1 รอบสำหรับบัตรโหวต 1 ใบ

ข้อ 4

4 / 10

What does the buggy code show for the input EEEE?โค้ดที่มี bug แสดงผลอะไรเมื่อป้อน EEEE?

เฉลย / Answerซ่อนเฉลย / Hide

เฉลย / Answer: (C) Winner: E and Votes: 1Winner: E และ Votes: 1

คำอธิบายแต่ละตัวเลือก / Explanation for each choice

  • (A) Winner: E and Votes: 4Winner: E และ Votes: 4
    Wrong: this is the expected output, but the buggy code counts only the first ballot for E.ผิด: นี่คือผลที่ควรได้ แต่โค้ดที่มี bug นับเฉพาะบัตรโหวตใบแรกของ E
  • (B) Winner: E and Votes: 0Winner: E และ Votes: 0
    Wrong: the += 1 line runs once when E first appears, so the count is 1.ผิด: บรรทัด += 1 ทำงานครั้งหนึ่งตอนพบ E ครั้งแรก คะแนนจึงเป็น 1
  • (C) Winner: E and Votes: 1Winner: E และ Votes: 1
    Correct! The last 3 ballots are not counted, because E is already in tally.ถูกต้อง! บัตรโหวต 3 ใบหลังไม่ได้ถูกนับ เพราะ E อยู่ใน tally แล้ว
  • (D) KeyError: 'E'KeyError: 'E'
    Wrong: E was added as a key, so reading tally['E'] gives no error.ผิด: E ถูกเพิ่มเป็น key แล้ว การอ่าน tally['E'] จึงไม่เกิด error

ข้อ 5

5 / 10

Which line holds the bug?bug อยู่ที่บรรทัดไหน?

เฉลย / Answerซ่อนเฉลย / Hide

เฉลย / Answer: (A) tally[vote] += 1tally[vote] += 1

คำอธิบายแต่ละตัวเลือก / Explanation for each choice

  • (A) tally[vote] += 1tally[vote] += 1
    Correct! This line is indented inside the if, so it does not run for a candidate who is already there.ถูกต้อง! บรรทัดนี้ย่อหน้าอยู่ใน if จึงไม่ทำงานกับบัตรโหวตของผู้สมัครที่มีอยู่แล้ว
  • (B) tally[vote] = 0tally[vote] = 0
    Wrong: a new candidate must start at 0; this line is right.ผิด: ผู้สมัครใหม่ต้องเริ่มที่ 0 บรรทัดนี้ถูกต้องแล้ว
  • (C) if tally[name] > most:if tally[name] > most:
    Wrong: > keeps the first one on a tie, as the problem asks.ผิด: > ทำให้คะแนนเท่ากันตอบคนที่พบก่อน ตรงตามโจทย์
  • (D) most = 0most = 0
    Wrong: every candidate has at least 1 vote, which is always more than 0.ผิด: ผู้สมัครทุกคนมีอย่างน้อย 1 คะแนน จึงมากกว่า 0 เสมอ

ข้อ 6

6 / 10

How should the bug be fixed?ควรแก้ bug อย่างไร?

เฉลย / Answerซ่อนเฉลย / Hide

เฉลย / Answer: (D) Move tally[vote] += 1 4 spaces to the left so it lines up with ifเลื่อน tally[vote] += 1 ไปทางซ้าย 4 ช่องให้ตรงกับ if

คำอธิบายแต่ละตัวเลือก / Explanation for each choice

  • (A) Change > most to >= mostเปลี่ยน > most เป็น >= most
    Wrong: every count is still 1, and a tie would now give the last candidate.ผิด: คะแนนยังเป็น 1 ทุกคน และคะแนนเท่ากันจะตอบคนสุดท้ายแทน
  • (B) Change tally[vote] = 0 to tally[vote] = 1เปลี่ยน tally[vote] = 0 เป็น tally[vote] = 1
    Wrong: every candidate would get 2 votes, and later ballots would still not be counted.ผิด: ผู้สมัครทุกคนจะได้ 2 คะแนน และบัตรโหวตใบต่อๆ ไปยังไม่ถูกนับ
  • (C) Delete the line if vote not in tally:ลบบรรทัด if vote not in tally:
    Wrong: tally[vote] = 0 would run every time and wipe out the earlier count.ผิด: tally[vote] = 0 จะทำงานทุกครั้ง คะแนนเดิมจึงถูกล้างทุกรอบ
  • (D) Move tally[vote] += 1 4 spaces to the left so it lines up with ifเลื่อน tally[vote] += 1 ไปทางซ้าย 4 ช่องให้ตรงกับ if
    Correct! The line then runs for every ballot, not only the first one of each candidate.ถูกต้อง! บรรทัดนี้จะทำงานกับบัตรโหวตทุกใบ ไม่ใช่เฉพาะใบแรกของแต่ละคน

ข้อ 7

7 / 10

What does the program show for an empty input (no ballots)?ถ้ากดส่งข้อมูลว่าง (ไม่มีบัตรโหวต) โปรแกรมแสดงอะไร?

เฉลย / Answerซ่อนเฉลย / Hide

เฉลย / Answer: (B) It shows Winner: and then stops with KeyError: ''แสดง Winner: แล้วหยุดด้วย KeyError: ''

คำอธิบายแต่ละตัวเลือก / Explanation for each choice

  • (A) Winner: and Votes: 0Winner: และ Votes: 0
    Wrong: tally is empty, so there is no key that holds 0.ผิด: tally ว่างเปล่า จึงไม่มี key ให้อ่านคะแนน 0
  • (B) It shows Winner: and then stops with KeyError: ''แสดง Winner: แล้วหยุดด้วย KeyError: ''
    Correct! winner is still "" and tally[""] does not exist, so a run-time error stops the program.ถูกต้อง! winner ยังเป็น "" และ tally[""] ไม่มีอยู่ จึงเกิด run-time error
  • (C) A SyntaxError before the program startsSyntaxError ก่อนเริ่มรัน
    Wrong: the input does not change the grammar of the code.ผิด: ข้อมูลที่ป้อนไม่ได้เปลี่ยนไวยากรณ์ของโค้ด
  • (D) Nothing at allไม่แสดงอะไรเลย
    Wrong: the line print("Winner:", winner) runs before the error.ผิด: บรรทัด print("Winner:", winner) ทำงานก่อนเกิด error

ข้อ 8

8 / 10

In the fixed code, why does ABBA give Winner: A?ในโค้ดที่แก้แล้ว ทำไม ABBA จึงตอบ Winner: A?

เฉลย / Answerซ่อนเฉลย / Hide

เฉลย / Answer: (C) Because A is the first key of tally, and > does not replace it when B only tiesเพราะ A เป็น key แรกของ tally และ > ไม่แทนที่เมื่อ B ได้คะแนนแค่เท่ากัน

คำอธิบายแต่ละตัวเลือก / Explanation for each choice

  • (A) Because A comes before B in the alphabetเพราะ A มาก่อน B ตามลำดับตัวอักษร
    Wrong: the program does not sort letters; BAAB would give B.ผิด: โปรแกรมไม่ได้เรียงตัวอักษร BAAB จะตอบ B
  • (B) Because A has more votes than Bเพราะ A ได้คะแนนมากกว่า B
    Wrong: A and B both have 2 votes.ผิด: A และ B ได้ 2 คะแนนเท่ากัน
  • (C) Because A is the first key of tally, and > does not replace it when B only tiesเพราะ A เป็น key แรกของ tally และ > ไม่แทนที่เมื่อ B ได้คะแนนแค่เท่ากัน
    Correct! The loop visits the keys in the order they were added, so A comes first, and 2 > 2 is false.ถูกต้อง! loop ไล่ key ตามลำดับที่เพิ่ม A จึงถูกตรวจก่อน และ 2 > 2 เป็นเท็จ
  • (D) Because find_winner reads the text from the endเพราะ find_winner อ่านข้อความจากท้ายมาหน้า
    Wrong: find_winner does not read the text; it visits the keys of tally.ผิด: find_winner ไม่ได้อ่านข้อความ แต่ไล่ key ของ tally

ข้อ 9

9 / 10

If > is changed to >= in the fixed code, what does ABBA give?ถ้าในโค้ดที่แก้แล้ว เปลี่ยน > เป็น >= ข้อมูล ABBA จะให้ผลอะไร?

เฉลย / Answerซ่อนเฉลย / Hide

เฉลย / Answer: (D) Winner: B and Votes: 2Winner: B และ Votes: 2

คำอธิบายแต่ละตัวเลือก / Explanation for each choice

  • (A) Winner: A and Votes: 2Winner: A และ Votes: 2
    Wrong: >= is true on a tie, so B replaces A.ผิด: >= เป็นจริงเมื่อคะแนนเท่ากัน B จึงแทนที่ A
  • (B) KeyError: 'B'KeyError: 'B'
    Wrong: B is a key of tally, so there is no error.ผิด: B เป็น key ของ tally จึงไม่เกิด error
  • (C) Winner: A and Votes: 1Winner: A และ Votes: 1
    Wrong: that is the output of the buggy code, but this question uses the fixed code.ผิด: นี่คือผลของโค้ดที่มี bug แต่โจทย์ข้อนี้ใช้โค้ดที่แก้แล้ว
  • (D) Winner: B and Votes: 2Winner: B และ Votes: 2
    Correct! 2 >= 2 is true, so B, which comes later, replaces A; this breaks the rule of the problem.ถูกต้อง! 2 >= 2 เป็นจริง B ที่มาทีหลังจึงแทนที่ A ซึ่งขัดกับกติกาของโจทย์

ข้อ 10

10 / 10

After the buggy code runs count_votes("BAB"), what is tally?หลังโค้ดที่มี bug รัน count_votes("BAB") จบ tally มีค่าเท่าไร?

เฉลย / Answerซ่อนเฉลย / Hide

เฉลย / Answer: (A) {'B': 1, 'A': 1}{'B': 1, 'A': 1}

คำอธิบายแต่ละตัวเลือก / Explanation for each choice

  • (A) {'B': 1, 'A': 1}{'B': 1, 'A': 1}
    Correct! The second B is not counted, because vote not in tally is false.ถูกต้อง! B ใบที่สองไม่ถูกนับ เพราะ vote not in tally เป็นเท็จ
  • (B) {'B': 2, 'A': 1}{'B': 2, 'A': 1}
    Wrong: that is the result of the fixed code.ผิด: นี่คือผลของโค้ดที่แก้แล้ว
  • (C) {'B': 0, 'A': 0}{'B': 0, 'A': 0}
    Wrong: the += 1 line still runs once when each candidate first appears.ผิด: บรรทัด += 1 ยังทำงานครั้งหนึ่งตอนพบผู้สมัครแต่ละคนครั้งแรก
  • (D) {'A': 1, 'B': 1}{'A': 1, 'B': 1}
    Wrong: a dictionary keeps its keys in the order they were added, and B was added first.ผิด: dictionary เก็บ key ตามลำดับที่เพิ่ม B ถูกเพิ่มก่อน