Tag Archives: ไพธอน

วิทย์ม.ต้น: Leap Year, Birthday Paradox, The Monty Hall Problem, ฝึก TrackeR

วิทย์โปรแกรมมิ่งวันศุกร์นี้ เด็กๆม.3 ดูเฉลยการบ้านเรื่องหาวันที่เป็น palindrome คืออ่านกลับหลังก็เหมือนอ่านปกติเช่นวันที่ 2020-02-02 ครับ ในการบ้านเด็กๆต้องไปหาวิธีหาว่าปีไหนมี 366 วัน (เป็น leap year) ด้วย กฎเกณฑ์คือดูปีเป็น ค.ศ. แล้วดูว่าถ้าปีหารด้วย 4 ลงตัวก็เป็น leap year แต่ถ้าหารด้วย 100 ลงตัวก็ไม่นับเป็น leap year แต่ถ้าหารด้วย 400 ลงตัวก็นับเป็น leap year

สาเหตุที่ต้องมีกฎเกณฑ์แบบนี้เพราะว่าโลกใช้เวลาประมาณ 365.242189 วัน (หรือ 365 วัน 5 ชั่วโมง 48 นาที 45 วินาที) คือในหนึ่งปีจะมีวันเกิน 365 วันไปเกือบๆ 1/4 วัน เราจึงต้องพยายามชดเชยประมาณเกือบๆทุกๆ 4 ปี

วิธีเขียนฟังก์ชั่นหา leap year ก็จะมีหน้าตาประมาณนี้ครับ:

ถ้าเขียนตามวิธีที่ Wikipedia แสดงไว้ก็จะมีหน้าตาแบบนี้:

เช็คดูว่าปีต่างๆมีจำนวนวันอย่างที่คาดหรือเปล่า ในสองพันปีมี leap year 485 ปีใช่ไหม และฟังก์ชั่น is_leap_year และ is_leap_year1 ทำงานเหมือนกันใช่ไหม:

ต่อจากนั้นผมก็แนะนำให้เด็กๆม. 3 รู้จักกับ Birthday Paradox ที่สมมุติว่าทุกปีมี 365 วัน และแต่ละวันมีคนเกิดเท่าๆกัน ดังนั้นถ้ามีคนเกิน 365 คนก็ต้องมีวันเกิดซ้ำกันแน่ๆ ถ้ามีคนเดียวก็ไม่มีวันเกิดซ้ำกันได้ ถ้ามีสองคนโอกาสที่วันเกิดจะซ้ำกันคือ 1/365 คำถามก็คือต้องมีคนสักกี่คนถึงจะมีโอกาสมีวันเกิดซ้ำกันประมาณ 50%

เด็กๆเดากันว่าอาจจะต้องมีสัก 100 คน เราจึงเขียนโปรแกรมคำนวณความน่าจะเป็นที่จะมีวันเกิดซ้ำกันถ้ามีคน k คนครับ

วิธีคำนวณง่ายที่สุดคือให้สังเกตว่าถ้าให้ p = ความน่าจะเป็นที่จะมีวันเกิดซ้ำกันในกลุ่มคน k คน และ q = ความน่าจะเป็นที่ไม่มีวันเกิดซ้ำกันเลยในกลุ่มคน k คนแล้ว จะได้ว่า p = 1 – q แล้วก็ไปคำนวณ q กันก่อน

สำหรับ k = 1 คน, q = 1 เพราะคน 1 คนไม่สามารถมีวันเกิดซ้ำกับใคร
สำหรับ k = 2 คน, q = 364/365 คือคนที่สองต้องเกิดไม่ซ้ำกับคนแรก
สำหรับ k = 3 คน, q = 364/365 x 363/365 คือคนที่สามก็ต้องไม่ซ้ำกับคนที่สองด้วย
ถ้าไล่ไปเรื่อยๆ สำหรับ k คน, q จะเท่ากับ (365-k+1)/365 คูณกับ q ของ k-1 คน

พอคำนวณ q เสร็จเราก็คำนวณ p จาก p = 1 – q

ให้เด็กๆม.3 ไปทำเป็นการบ้านคือเขียนโปรแกรมคำนวณ p, q และตอบคำถามว่าต้องมีคนสักกี่คนถึงจะมีโอกาสวันเกิดซ้ำกันบ้างประมาณ 50% ครับ

นอกจากนี้ผมยังให้เด็กๆม. 3 รู้จัก The Monty Hall problem (แปลเป็นภาษาไทยที่นี่) ด้วยครับ สถานการณ์เป็นแบบนี้:

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

จาก https://th.wikipedia.org/wiki/ปัญหามอนตี_ฮอลล์

คนส่วนใหญ่จะคิดว่าเปลี่ยนหรือไม่เปลี่ยนประตูก็น่าจะมีโอกาสชนะเท่าๆกัน แต่จริงๆไม่ใช่อย่างนั้นครับ

ผมให้เด็กๆดูคลิปนี้ช่วงแรกก่อนเฉลย:

และการบ้านของเด็กๆคือไปเขียนโปรแกรมจำลองการเล่นเกมนี้เป็นพันๆครั้ง ดูว่าถ้าเปลี่ยนประตูจะมีโอกาสชนะเท่าไร ถ้าไม่เปลี่ยนประตูจะมีโอกาสชนะเท่าไรครับ

สำหรับเด็กม.1 ผมให้หัดใช้โปรแกรม Tracker เพื่อวัดระยะทาง ความเร็ว ความเร่งในวิดีโอคลิปต่างๆของเรากันครับ เป็นโปรแกรมฟรี open source และมีบน Windows, macOS, Linux

ผมเคยบันทึกตัวอย่างการใช้ไว้ที่นี่ครับ:

คราวนี้เด็กๆวัดการสั่นของตุ้มน้ำหนักที่ผูกกับหนังยางต่อกันสามเส้น และแบบหนังยางต่อกัน 6 เส้นครับ ให้สังเกตว่าคาบการสั่นต่างกันอย่างไร อันไหนใช้เวลามากกว่าในการสั่นหนึ่งรอบ หน้าตาโปรเจ็คเป็นแบบนี้ครับ:

วิทย์ม.ต้น: ใช้ SymPy แก้สมการสัญญลักษณ์และตัวเลข, สั่งให้คอมพิวเตอร์ทำงานซ้ำๆแทนเรา

วิทย์โปรแกรมมิ่งวันศุกร์ครั้งนี้ เด็กม.3 ดูโจทย์นี้เพื่อแปลงเป็นสมการให้ SymPy แก้ปัญหาให้ครับ

เราแปลงเป็นสมการในตัวแปร x, y, z ให้ SymPy แก้ได้แบบนี้ครับ:

เราเอาค่า x, y, z ไปแทนค่าได้แบบนี้ คำตอบคือ 41:

ทดลองหาจุดตัดของวงกลมและเส้นตรงครับ:

ใช้คำสั่ง div หาผลหารและเศษการหารโพลีโนเมียลได้ด้วยครับ:

สำหรับเด็กม.1 เราพยายามหาค่า x ที่ทำให้ xx = 2 (จากตอนท้ายของวิดีโอข้างบน) เราทำโดยเดาก่อนว่า 11 = 1 และ 22 = 4 ดังนั้น x น่าจะอยู่ระหว่าง 1 กับ 2 แล้วเด็กๆก็ลองดูตรงกลางระหว่าง 1 กับ 2 ว่า 1.51.5 = 1.84… แสดงว่าคำตอบควรอยู่ระหว่าง 1.5 กับ 2 จึงลองดูตรงกลาง = 1.75 พบว่า 1.751.75 = 2.66 แสดงว่าคำตอบควรอยู่ระหว่าง 1.5 กับ 1.75 ถ้าเราทำต่อไปเราก็จะหาทางแบ่งครึ่งช่วงคำตอบไปเรื่อยๆ แต่เราหัดเขียนโปรแกรมให้คอมพิวเตอร์ไล่ให้เราได้ดังนี้ครับ:

พบว่า x = 1.5596104694623696…. จะทำให้ xx = 2 ครับ

ผมถามเด็กว่าถ้าจะหาค่า x ที่ทำให้ xx = 3 จะทำอย่างไร เด็กๆก็แก้โปรแกรมนิดนึงได้คำตอบ x = 1.8254550229248308… ทำให้ xx = 3 ครับ:

ผมถามเด็กม.1 ด้วยว่าถ้าคำนวณ (1+1/1)1, (1+1/2)2, (1+1/3)3, (1+1/4)4, …, (1+1/n)n โดยที่ n ใหญ่ขึ้นไปเรื่อยๆ ค่าที่คำนวณจะใหญ่ไปเรื่อยๆไหม เด็กๆก็ให้ไพธอนคำนวณให้ พบว่าผลการคำนวณจะประมาณ 2.71828… (ซึ่งเท่ากับค่าคงที่ออยเลอร์หรือค่า e นั่นเองครับ)

วิทย์ม.ต้น: หัดใช้ SymPy สำหรับโจทย์เลขสัญญลักษณ์, ใช้ Microsoft Math ช่วยแก้และสร้างโจทย์

วิทย์โปรแกรมมิ่งวันศุกร์นี้ สำหรับม.3 ผมให้ดูคลิปโจทย์นี้ก่อน:

โจทย์คือโทรศัพท์ต้องมีรหัสตัวเลขสี่หลัก มีรหัสกี่อันที่ไม่มีเลข 13 อยู่ในนั้น (ดูเฉลยในคลิปได้ครับ) แต่ผมให้เด็กๆเขียนโปรแกรมไล่นับดูด้วย หน้าตาโปรแกรมก็เป็นแบบนี้:

หลังจากทำอย่างนี้ได้ผมก็ถามว่าถ้านับจำนวนรหัสที่ห้ามมีเลข 1 แล้วมีเลข 3 อยู่ด้านหลังโดยอาจมีเลขอื่นๆคั่นอยู่จะนับอย่างไร เด็กๆก็เข้าใจว่าต้องไปเปลี่ยนเงื่อนไขว่าพบเลข 1 และ เลข 3 และเลข 3 ต้องอยู่ด้านหลังเลข 1 แต่เด็กๆไม่รู้ว่าคำสั่งที่ใช้หาตำแหน่งคืออะไร ผมจึงค้นหาในเว็บให้เด็กๆดู พบว่าใช้คำสั่ง find ได้เช่นที่เว็บนี้ พอเรารู้ว่าใช้ find อย่างไร โปรแกรมไล่นับของเราก็จะมีหน้าตาประมาณนี้ครับ:

จากนั้นเด็กๆม.3 ดูตัวอย่างวิธีใช้ SymPy ในโปรแกรมไพธอน ตามตัวอย่างที่หน้านี้ครับ สามารถใช้แก้ปัญหาคณิตศาสตร์แบบติดสัญญลักษณ์ได้ (แก้แบบ symbolic ) หน้าตาก็เป็นประมาณนี้:

ผมได้เล่าเรื่องจำนวนเชิงซ้อน (complex numbers) ให้เด็กๆฟังว่าจริงๆแล้วตัวเลขไม่ได้อยู่บนเส้นจำนวนเท่านั้น ระนาบรอบๆเส้นจำนวนก็มีตัวเลขเต็มไปหมด เลขเหล่านั้นถูกเรียกว่าจำนวนเชิงซ้อน แต่จริงๆมันก็มีตัวตนเหมือนเลขบนเส้นจำนวนนั่นแหละ มีกฎเกณฑ์การบวกลบคูณหารที่แน่นอน กฎเกณฑ์ทางธรรมชาติและคณิตศาสตร์หลายๆอย่างก็ใช้เลขเหล่านี้ และวิธีคิดถึงตัวเลขเหล่านี้ที่จินตนาการง่ายๆก็คือลากเส้นลูกศรจาก 0 ไปที่เลขต่างๆ การบวกก็เหมือนการเอาลูกศรมาต่อกัน การคูณเหมือนกับเอาทิศทางของลูกศรมาบวกกันแล้วยืดลูกศรลัพธ์ให้ยาวเท่ากับผลคูณของความยาวลูกศรที่เอามาคูณกัน

สำหรับเด็กม.1 ผมให้โหลดโปรแกรม Microsoft Math มาใช้ในโทรศัพท์ สามารถถ่ายรูปโจทย์ต่างๆ หรือเขียนโจทย์ต่างๆเข้าไปให้โปรแกรมแก้ และแสดงขั้นตอนการทำให้ดูได้ด้วย หน้าตาเว็บเขาจะเป็นแบบนี้ครับ:

https://math.microsoft.com

เด็กๆหัดเอา Microsoft Math ไปลองแก้ปัญหาต่างๆ และตอนหลังเขาตั้งโจทย์กันแล้วดูว่า Microsoft Math แก้ได้ไหมด้วยครับ ยกตัวอย่างเช่นโจทย์ว่ามีสัตว์ห้าชนิดคือ ไก่ วัว เต่าทอง แมงป่องพิษ งูพิษ มีสัตว์รวมกัน 80 ตัว มีปีกรวมกัน 120 ปีก มีสัตว์มีพิษ 25 ตัว และมีขารวมกัน 370 ขา ให้หาว่ามีสัตว์แต่ละชนิดกี่ตัว

เราก็เขียนสมการของโจทย์ไปบนกระดาษ แล้วใช้ Microsoft Math ถ่ายรูป จะพบว่าถ้าให้จำนวน ไก่ วัว เต่าทอง แมงป่อง และงู เท่ากับ x y z w v ตามลำดับแล้ว x = (110-8v)/3, y = (4v+20)/3, z = (4v+35)/3 , w = 25-v คือจำนวนไก่ วัว เต่าทอง แมงป่องขึ้นกับจำนวนงู v ที่เราใส่เข้าไป ผมจึงให้เด็กๆเขียนโปรแกรมไล่ว่ามีคำตอบทั้งหมดกี่คำตอบอีกทีครับ คำตอบที่เป็นไปได้คือ x, y , z, w, v ต้องเป็นจำนวนเต็มไม่น้อยกว่าศูนย์ และผมแนะนำให้เด็กๆรู้จักกับฟังก์ชั่น divmod ที่หาผลหารและเศษการหารออกมา เพื่อเราจะได้เช็คว่าผลการหารของเราได้เป็นเลขจำนวนเต็มหรือไม่ หน้าตาโปรแกรมก็เป็นประมาณนี้ พบว่ามี 5 คำตอบ (ตอนเด็กตั้งโจทย์ เขาสร้างตัวเลขขึ้นมาชุดเดียวคือ 10, 20, 25, 15, 10):

จริงๆถ้าเราจะใช้ SymPy แก้ก็ได้เหมือนกันครับ: