Example 7 — Check a Palindrome with One Loop ตัวอย่างที่ 7 — ตรวจคำที่อ่านกลับหลังได้เหมือนเดิมด้วย loop เดียว
The same problem as Example 6, solved with one loop and no extra backward word. โจทย์เดียวกับตัวอย่างที่ 6 แต่เขียนด้วย loop เดียว และไม่ต้องสร้างคำกลับหลังเพิ่ม
This page solves the problem of Example 6 again, with a shorter program. Read the problem, follow the flowchart and run the code, then see in card 3 why this program is better than the one in Example 6.
หน้านี้แก้โจทย์ของตัวอย่างที่ 6อีกครั้งด้วยโปรแกรมที่สั้นกว่า อ่านโจทย์ ไล่ตาม flowchart และรันโค้ด แล้วดูในการ์ดที่ 3 ว่าโปรแกรมนี้ดีกว่าโปรแกรมในตัวอย่างที่ 6 อย่างไร
Read one word that contains only lowercase English letters, then tell whether the word reads the same forwards and backwards. A word like this is called a palindrome. If it does, show <word> reads the same both ways; if it does not, show <word> does not read the same both ways. A word of one letter and an empty word (nothing typed) both count as reading the same, because they have no pair of letters that differ.
รับคำ 1 คำที่มีเฉพาะตัวพิมพ์เล็กภาษาอังกฤษ แล้วบอกว่าคำนั้นอ่านจากหน้าไปหลังและหลังไปหน้าได้เหมือนกันหรือไม่ คำแบบนี้เรียกว่า palindrome ถ้าเหมือนกันให้แสดง <คำ> reads the same both ways ถ้าไม่เหมือนให้แสดง <คำ> does not read the same both ways คำที่มีตัวอักษรตัวเดียวและคำว่าง (ไม่พิมพ์อะไรเลย) นับว่าอ่านได้เหมือนกัน เพราะไม่มีตัวอักษรคู่ไหนที่ต่างกัน
- Example:ตัวอย่าง: level → level reads the same both ways
- Example:ตัวอย่าง: robot → robot does not read the same both ways
- word[i] is the letter at position i counted from the left, starting at 0.
- A negative index counts from the end: word[-1] is the last letter and word[-2] the one before it.
- word[-(i + 1)] is the letter at position i counted from the end: when i = 0 it is word[-1], the last letter; when i = 1 it is word[-2], and so on.
- != means “is not equal to”.
- mirror holds True or False and is used as a flag: it starts as True and changes to False as soon as a pair of letters differs.
- word[i] คือตัวอักษรตำแหน่งที่ i นับจากซ้าย เริ่มที่ 0
- ดัชนีติดลบนับจากท้าย word[-1] คือตัวสุดท้าย และ word[-2] คือตัวรองสุดท้าย
- word[-(i + 1)] คือตัวอักษรตำแหน่งที่ i นับจากท้าย เมื่อ i = 0 คือ word[-1] ตัวสุดท้าย เมื่อ i = 1 คือ word[-2] และต่อไปเรื่อยๆ
- != แปลว่า “ไม่เท่ากับ”
- mirror เก็บค่า True หรือ False ใช้เป็นตัวแปรธง คือตั้งไว้เป็น True ก่อน แล้วเปลี่ยนเป็น False เมื่อพบตัวอักษรคู่ที่ต่างกัน
The program starts by reading a word into word. Next it sets mirror = True as a flag that assumes the word reads the same, sets i = 0 as the letter position, and checks whether i < len(word). If it is, it checks whether word[i] != word[-(i + 1)], that is, whether the letter at position i from the left differs from the letter at position i from the end; if that is true it sets mirror = False. Either way it increases i by 1 and goes back to check i < len(word) again. This repeats until the condition is false; then it leaves the loop and checks whether mirror == True. If it is, it shows that the word reads the same both ways, otherwise it shows that it does not, with print, and the program ends.
โปรแกรมนี้เริ่มต้นด้วยรับคำจากผู้ใช้เก็บใน word ถัดไปกำหนดค่า mirror = True เป็นตัวแปรธงที่ถือว่าคำนี้อ่านได้เหมือนกันไว้ก่อน และกำหนดค่า i = 0 เป็นตัวชี้ตำแหน่งตัวอักษร แล้วตรวจสอบเงื่อนไขว่า i < len(word) หรือไม่ ถ้าใช่ให้ตรวจสอบเงื่อนไขว่า word[i] != word[-(i + 1)] หรือไม่ คือตัวอักษรตำแหน่งที่ i นับจากซ้าย ต่างจากตัวอักษรตำแหน่งที่ i นับจากท้ายหรือไม่ ถ้าใช่ให้กำหนด mirror = False ไม่ว่าทางใดทางหนึ่ง หลังจากนั้นเพิ่ม i ขึ้น 1 แล้วกลับไปตรวจสอบ i < len(word) อีกครั้ง ทำแบบนี้จนเงื่อนไขเป็นเท็จ จึงออกจาก loop แล้วตรวจสอบเงื่อนไขว่า mirror == True หรือไม่ ถ้าใช่ให้แสดงว่าคำนี้อ่านได้เหมือนกันทั้งสองทาง ถ้าไม่ใช่ให้แสดงว่าอ่านไม่เหมือนกัน ด้วย print และจบการทำงานของโปรแกรม
Type a word: level level reads the same both ways
Try it yourself — type a word and press Submit. It replaces the [input] box and runs the code that is in the box right now. Press Submit with an empty box to test an empty word.
ลองป้อนค่าเอง — พิมพ์คำแล้วกดส่ง คำจะแทนที่กล่อง [input] แล้วรันโค้ดที่อยู่ในกล่องตอนนี้ ถ้ากดส่งโดยไม่พิมพ์อะไรจะเป็นการทดสอบคำว่าง
| Inputข้อมูลที่ป้อน | Outputผลลัพธ์ |
|---|---|
| level | level reads the same both ways |
| racecar | racecar reads the same both ways |
| noon | noon reads the same both ways |
| robot | robot does not read the same both ways |
| ab | ab does not read the same both ways |
| x | x reads the same both ways |
| (empty)(ว่าง) | reads the same both ways (starts with a space: the empty word, then the space that print puts between its values) (ขึ้นต้นด้วยช่องว่าง: คำว่าง ตามด้วยช่องว่างที่ print ใส่คั่นระหว่างค่า) |
Example 6 (after its bug is fixed) works in two parts: the first loop builds backward letter by letter, and the second loop compares word[i] with backward[i]. But the letter at position i of backward is simply word[-(i + 1)], so there is no need to build backward first: this program reads each pair of letters straight from word.
ตัวอย่างที่ 6 (หลังแก้ bug) ทำงาน 2 ช่วง loop แรกสร้าง backward ทีละตัวอักษร และ loop ที่สองเทียบ word[i] กับ backward[i] แต่ตัวอักษรตำแหน่งที่ i ของ backward ก็คือ word[-(i + 1)] อยู่แล้ว จึงไม่ต้องสร้าง backward ก่อน โปรแกรมนี้อ่านตัวอักษรแต่ละคู่จาก word ได้เลย
| Example 6 (fixed)ตัวอย่างที่ 6 (หลังแก้ bug) | Example 7ตัวอย่างที่ 7 | |
|---|---|---|
| Number of loopsจำนวน loop | 2 (build backward, then compare)2 (สร้าง backward แล้วเทียบ) | 1 |
| Extra variableตัวแปรเพิ่ม | keeps a whole backward copy of the word in backwardเก็บคำกลับหลังทั้งคำไว้ใน backward | noneไม่มี |
| Rounds for a 5-letter word (level)จำนวนรอบเมื่อคำยาว 5 ตัว (level) | 10 (5 to add letters + 5 to compare)10 (ต่อตัวอักษร 5 + เทียบ 5) | 5 |
| Lines in the Process partจำนวนบรรทัดในส่วน Process | 7 | 4 |
Run the code below to see each pair that the loop compares. It is the program of card 2 with one print added inside the loop. For level every pair matches, so mirror stays True. Change the input to robot: the first pair, r and t, already differs, so mirror is False after round 0, yet the loop still runs all 5 rounds.
รันโค้ดด้านล่างเพื่อดูตัวอักษรแต่ละคู่ที่ loop เทียบ โค้ดนี้คือโปรแกรมในการ์ดที่ 2 ที่เพิ่ม print 1 บรรทัดใน loop สำหรับ level ทุกคู่ตรงกัน mirror จึงเป็น True ตลอด ลองเปลี่ยน input เป็น robot คู่แรก r กับ t ก็ต่างกันแล้ว mirror จึงเป็น False ตั้งแต่รอบที่ 0 แต่ loop ยังทำงานต่อจนครบ 5 รอบ
Type a word: level 0 -1 l l True 1 -2 e e True 2 -3 v v True 3 -4 e e True 4 -5 l l True mirror = True
Think further: in the output for level, round 0 compares l with l, and round 4 compares the same two letters again. Every pair is checked twice. How could the loop check each pair only once, and how many rounds would a 5-letter word need then?
ชวนคิดต่อ: ในผลของ level รอบที่ 0 เทียบ l กับ l และรอบที่ 4 ก็เทียบตัวอักษร 2 ตัวนี้ซ้ำอีกครั้ง ทุกคู่จึงถูกเทียบ 2 ครั้ง จะเขียน loop ให้เทียบแต่ละคู่เพียงครั้งเดียวได้อย่างไร และคำยาว 5 ตัวจะเหลือกี่รอบ
Show the answer ดูคำตอบ
Round i compares position i from the left with position i from the end, so once i passes the middle of the word the loop only repeats pairs it has already checked. For a word of N letters it is enough to check i = 0 up to i = (N - 1) // 2. When N is odd, the last of these rounds compares the middle letter with itself, which can never differ, so that round can be dropped too: i = 0 up to N // 2 - 1, which is range(len(word) // 2).
รอบที่ i เทียบตำแหน่งที่ i นับจากซ้ายกับตำแหน่งที่ i นับจากท้าย เมื่อ i เลยกึ่งกลางคำไปแล้ว loop จะเทียบซ้ำแต่คู่ที่ตรวจไปแล้ว สำหรับคำยาว N ตัว จึงตรวจแค่ i = 0 ถึง i = (N - 1) // 2 ก็พอ และเมื่อ N เป็นเลขคี่ รอบสุดท้ายของช่วงนี้คือการเทียบตัวกลางกับตัวเอง ซึ่งไม่มีทางต่างกัน จึงตัดรอบนี้ออกได้อีก เหลือ i = 0 ถึง N // 2 - 1 ซึ่งก็คือ range(len(word) // 2)
| Looploop | Rounds for level (N = 5)จำนวนรอบของ level (N = 5) | Rounds for noon (N = 4)จำนวนรอบของ noon (N = 4) |
|---|---|---|
| range(len(word)) (card 2)(การ์ดที่ 2) | 5 | 4 |
| range((len(word) - 1) // 2 + 1) | 3 | 2 |
| range(len(word) // 2) | 2 | 2 |
// is integer division: it divides and drops the part after the decimal point, for example 5 // 2 is 2. Use //, not /: 5 / 2 is 2.5, and range accepts only whole numbers, so the program would stop with a TypeError.
// คือการหารปัดเศษทิ้ง เช่น 5 // 2 ได้ 2 ต้องใช้ // ไม่ใช่ / เพราะ 5 / 2 ได้ 2.5 และ range รับเฉพาะจำนวนเต็ม โปรแกรมจะหยุดด้วย TypeError
Run the half-word loop below. For level it checks only 2 pairs and still gives the same answer; try noon, robot and x too.
รัน loop แบบครึ่งคำด้านล่าง สำหรับ level ตรวจแค่ 2 คู่ก็ได้คำตอบเหมือนเดิม ลองป้อน noon, robot และ x ด้วย
Type a word: level 0 -1 l l True 1 -2 e e True mirror = True
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 / แหล่งอ้างอิง
- Python docs — Common Sequence Operations (indexing a string, including negative indexes counted from the end) (การใช้ดัชนีกับสตริง รวมถึงดัชนีติดลบที่นับจากท้าย)
-
Python docs — Comparisons
(
!=and==) (!=และ==) -
Python docs — Numeric Types
(
//, integer division, used in the answer of “Think further”) (//การหารปัดเศษทิ้ง ใช้ในคำตอบของ “ชวนคิดต่อ”) -
Python docs — Boolean Type
(
TrueandFalse) (TrueและFalse) - The two-loop version of this program: Example 6 — Check a Palindrome (debugging); flowchart symbols: 01 Basic → Flowchart Basic. โปรแกรมแบบ 2 loop ของโจทย์นี้: ตัวอย่างที่ 6 — ตรวจคำที่อ่านกลับหลังได้เหมือนเดิม (debugging) ; สัญลักษณ์ของ flowchart: 01 Basic → Flowchart Basic