ใครยังไม่ได้อ่าน อยากเขียนโปรแกรม เริ่มยังไงดี? (1) ซึ่งเป็นภาคแรกกลับไปอ่านก่อนได้นะ
หายไปซะนานข้ามปี ในบทความที่แล้วเราพูดกันค้างถึง Algorithm ก็ไว้
วันนี้จะมาพูดต่อถึงสิ่งที่เรียกว่าสำคัญที่สุดในการเขียนโปรแกรมก็ว่าได้
Algorithm ขั้อตอนวิธี (แบบเถรตรงตามตัวอักษร) ไปสู่จุดหมาย
สำหรับ Algorithm ที่ภาษาไทยแปลออกมาได้ว่า ขั้นตอนวิธี อืม.. แม้จะแปลออกมาแล้วก็ยังไม่ค่อยเห็นภาพอยู่ดีว่ามันคืออะไร
ถ้าจะอธิบายง่ายๆ ก็คือวิธีที่จะทำให้เราได้ผลลัพท์อย่างที่เราต้องการ โดยหลักสำคัญของมันคือ
- อัลกอริทึมต้องเป็นขั้นตอน
- อัลกอริทึมต้องละเอียดพอที่จะไม่ทำให้สับสนได้
- อัลกอริทึมต้องทำออกมาแล้วได้ผลเหมือนกันทุกครั้ง
ซึ่งหลายๆ ครั้งที่อัลกอริทึมมันเขียนวิธีออกมาที่ขัดกับความคิดของคนส่วนใหญ่ (ที่เป็นมนุษย์) เพราะคนเราสามารถตีความและเข้าใจความหมายจากประโยคสั้นๆ ที่คลุมเครือได้
คนเราอาจจะใช้วิธีที่ตรงไปตรงมาได้ แต่คอมพิวเตอร์ทำแบบนั้นไม่ได้ |
ยกตัวอย่างเช่น
ต้มมาม่าต้องใช้เวลา 3 นาทีนะ
ไปต้มมาม่ามาให้กินหน่อยซิ!
เอาล่ะ ถ้าคุณต้องไปต้มมาม่า คุณจะทำอะไรบ้าง
- เอามาม่าใส่ถ้วย
- ต้มน้ำร้อนแล้วเทใส่ถ้วย
- หาฝาผิดไว้
- รอ 3 นาที
จบแล้วป่ะ?
ใช่...ง่ายๆ แค่นี้เราก็ได้มาม่ามากินกันแล้ว แล้วแบบนี้ใช่อัลกอริทึมรึเปล่า
มันก็ใช่นะ แต่ดูเหมือนจะละเอียดไม่พอ
ลองคิดว่าคนที่คุณสั่งให้เขาไปทำน่ะโง่มากๆ ดูสิ
A: ไปต้มมาม่ามาให้หน่อย ทำตาม 4 ขั้นตอนข้างบนเลยนะ
Foo: เดินไปที่ห้องครัวหยิบมาม่าที่ยังอยู่ในซองใส่ถ้วย -> ต้มน้ำร้อนจนมันร้อนนิดหน่อย -> เทใส่ถ้วยไปแค่ครึ่งถ้วย -> หาฝามาปิด -> รอ 3 นาที
A: เดินมาหยิบมาม่าเตรียมตัวกินแล้วก็ต้องตกใจ!!
ประมาณนั้นแหละ ถ้าเราสั่งไม่ดี นายFoo คนนี้ก็จะทำงานให้เราแบบมึนๆ
นี่เป็นเรื่องจริงที่เปิดขึ้นกับโปรแกรมเมอร์ทุกคน เราต้องสั่งคอมพิวเตอร์ที่โง่กว่า นายFoo คนนี้เสียอีก (ถ้าคุณบอกว่าคอมพิวเตอร์ฉลาด เช่นฉันเปิด google จะหาข้อมูล มันยังแนะนำเว็บไซต์ที่ฉันอยากได้มาให้ตรงเป๊ะเลยนะ ... นั่นไม่ใช่คอมพิวเตอร์ฉลาดหรอกครับ แต่เป็นโปรแกรมเมอร์ที่เป็นคนสั่งคอมพิวเตอร์พวกนี้อีกทีที่ฉลาด)
งั้นเอาใหม่
- ฉีกมาม่าออกจากซอง
- ใส่มาม่าลงใสถ้วย
- ถ้ามีเครื่องปรุงในซอง -> แกะเครื่องปรุงใส่ถ้วยด้วย
- ต้มน้ำในปริมาณ 1 ถ้วยจนน้ำเดือด
- เทน้ำลงในถ้วยจนระดับน้ำห่างจากขอบ 1 นิ้ว
- ใช้ตะเกียงคนเครื่องปรุงให้ละลายในน้ำให้หมด
- เอาฝาปิดถ้วยไว้ให้สนิท
- ทำแบบนี้ 3 รอบ -> รอ 1 นาที เปิดฝาคนเส้น 3 ครั้ง แล้วปิดฝาไปใหม่
- เปิดฝา (มาม่าเสร็จแล้ว)
ดูยุ่งยากจัง .. ใช่แล้ว อัลกอริทึมที่ดีต้องละเอียดในระดับที่ไม่ว่าใครจะมาทำงานโดย follow วิธีและขั้นตอนพวกนี้ ผลลัพท์จะต้องออกมาเหมือนกันทุกครั้ง
ถ้าการต้มมาม่ายังทำให้เห็นภาพไม่ชัด เรามาดูตัวอย่างในเชิงคณิตศาสตร์กันบ้างดีกว่า
ชั่วโมงเลข ป.1
คาบเลข คุณครูเดินเข้ามาพร้อมกับบอกให้นักเรียนทำโจทย์บอกเลข 10 ตัว!!
ในเมื่อคะแนนจิตพิสัยอยู่ในกำมือคุณครู พวกเราก็ต้องมานั่งบวกเลขพวกนี้กันไป
เอ้า ตัวที่หนึ่ง บวกตัวที่สอง ได้เท่าไหร่เอาไปบวกตัวที่สาม ได้เท่าไหร่เอาไปบวกตัวที่สี่ บลาๆๆๆ...จนครบ 10 ตัว
ได้คำตอบแล้วคร้าบ ตอบเท่านี้ๆ เย้
คุณครูของคุณได้ฟังก็พยักหน้าบอกว่า ถูกต้อง (เก่งนะ บวกครั้งแรกถูกเลย) แล้วก็ให้โจทย์มาอีกข้อ
มาถึงตอนนี้คุณเริ่มขี้เกียจแล้ว จะให้ทำอะไรซ้ำๆ หลายๆ รอบทำไม
แล้วตอนนั้นเอง คุณก็คิดถึงสิ่งหนึ่งที่จะทำงานแทนคุณได้โดยไม่ปริปากบ่นแม้จะเป็นงานที่ซ้ำๆ และน่าเบื่อแค่ไหนก็ตาม
คุณเลยหันไปเปิดคอมพิวเตอร์ของคุณเพื่อจะให้มันบวกเลขแทนคุณ
แต่ .. คุณจะสั่งมันว่ายังไงล่ะ
ลองมาดูวิธีที่โปรแกรมเมอร์สั่งคอมให้คิดแทนกันดีกว่า
- ถือว่าผลบวกของจำนวนทั้งหมดคือ sum
- ตอนแรกให้กำหนด sum เท่ากับ 0 เสียก่อน (ยังไม่ได้เริ่มบวก เลยยังไม่มีผลรวม)
- ให้ i เป็นสิ่งที่เอาไว้นับว่าบวกเลขไปถึงตัวที่เท่าไหร่แล้ว
- กำหนด i เท่ากับ 1 (เพราะเริ่มที่ตัวแรก)
- ถ้า i ยังไม่มากกว่า 10 เราจะกำหนดให้: sum มีค่าเท่ากับ ค่า sumเดิม + กับตัวเลขตัวที่ i
(เช่นรอบแรก i เป็น 1 ตัวเลขตัวที่ 1 คือ [2] ดังนั้นเอา sum + 2 จะได้ 0 + 2 จะได้ 2 .. แล้วเราก็เอา 2 เนี่ยไปเก็บไว้ใน sum ซะ ) - เพิ่มค่าให้ i อีก 1 (เพื่อขยับไปยังเลขตัวถัดไป)
- กลับไปเช็กข้อ 5 ใหม่อีกรอบ (ทำแบบนี้ไปเรื่อยๆ จน i มากกว่า 10 นั่นหมายความว่ามันบวกครบ 10 ตัวแล้ว)
อือ...นี่แค่สั่งให้บวกเลขไม่กี่ตัวเท่านั้นนะ ปาเข้าไป 7 บรรทัด 7 ขั้นตอนแล้ว
เชื่อว่าหลายๆ คนคงบอกว่า "ยุ่งยากขนาดนี้ บวกเองเสร็จไปนานแล้ว"
มันก็จริง ถ้าคุณยังเขียนโปรแกรมไม่เก่ง ทนบวกเองไปเรื่อยๆ น่าจะเสร็จเร็วกว่าเขียนโปรแกรมขึ้นมาเพื่อให้คอมพิวเตอร์แก้โจทย์ให้อยู่แล้วล่ะ
สำหรับใครที่อยากลองทำดูบ้างผู้เขียนขอทิ้งโจทย์ไว้ให้ว่า...
"คุณครูคนเก่งของคุณให้คุณฝึกบวกเลขมาเยอะแล้ว ทีนี้เขาจะให้คุณลองทำอีกอย่างที่ง่ายขึ้น คือถามว่าตัวเลขมากที่สุดในชุดตัวเลข 10 ตัวเนี้ย ถ้าเอามาลบกับตัวเลขที่น้อยที่สุดในชุดตัวเลข10เดิมจะได้คำตอบเป็นเท่าไหร่"
โอ้ ... คำถามแบบนี้ ง่ายกว่าเดิมอีกใช่ไหม แค่กวาดตารอบเดียวก็หาเจอแล้วว่าตัวไหนมากสุดและน้อยสุด จากนั้นเอามาลบกัน ไม่เห็นต้องคิดเลขอะไรเยอะๆ แบบข้อที่แล้วเลย
เชื่อเถอะครับ! ว่าโจทย์อันที่สองนี่เวลาเอาไปเขียนโปรแกรมแล้วยากกว่าตัวอย่างแรกเยอะ
เหตุผลคือ ตัวอย่างแรกนั้นมีความซับซ้อนน้อยกว่า เพราะว่าเราไม่ได้ทำอะไรเลยนอกจาก "บวก" ไงล่ะ คอมพิวเตอร์ชอบโจทย์ที่ถึกๆ แต่ไม่มีความซับซ้อนมากกว่าโจทย์ง่ายๆ ที่มีความซับซ้อนอย่างการหาตัวเลข "มากที่สุด" ที่มีอะไรมากกว่าที่คิดเวลาคุณเอาไปเขียนโปรแกรม
ลองถามตัวเองดู ว่าเวลาคุณเหลือบขึ้นไปมองชุดตัวเลขพวกนี้ คุณรู้ได้ยังไงว่าตัวไหนมากที่สุด (หรือน้อยที่สุด)
เอ้า ... ต่างคนต่างวิธีคิดนะ อย่างเช่นของเรา เรามองตัวเลขแบบกวาดสายตาก่อนจนไปสะดุดตาที่ 12 เพราะมันมี 2 หลัก ตัวอื่นมันมีแค่หลักเดียว ยังไงเจ้านี่ก็ต้องมากสุดอยู่แล้วจริงป่ะ?
ส่วนเลขน้อยสุด เรากวาดสายตาไปจนเจอ 1 ตัวแรก ตามสัญชาติญาณของคนทั่วๆ ไปเนี่ย เลข 1 มันน่าจะเป็นเลขที่เล็กที่สุดแล้วนะ เพราะเมื่อกี้ก็ไม่เห็นเครื่องหมาย - (ติดลบ) เลย เลขศูนย์ก็ไม่เห็น งั้นเจ้านี่ก็คงน้อยสุดแหละ
จะเห็นว่าขั้นตอนการ "กวาดสายตา" ของคนมันซับซ้อน และเข้าใจยากเกินไป ตัวอย่างแบบนี้แหละที่ไม่เหมาะกับการคิดถึกๆ ของคอมพิวเตอร์
ใครว่างๆ ก็ลองเอาไปเขียน algorithm ดูละกัน ถ้าเขียนออกมาแล้วไม่แน่ใจว่ามันถูกรึเปล่าจะคอมเม้นท์ไว้ก็ได้ แล้วเราจะกลับมาตอบให้นะ
อืม...ตอนหน้าเขียนเรื่องอะไรดีนะ ^ ^