สวัสดีทุกคนที่เข้ามาอ่านนะครับ สำหรับบทแรกนี้จะเป็น overall introduction เกี่ยวกับคอร์สนี้ รวมไปถึงคำถามที่พบบ่อยต่าง ๆ ก่อนที่จะเริ่มไปเข้าเนื้อหาจริง ๆ จัง ๆ ในบทที่ 2 แต่ก่อนที่จะไปเริ่มลงรายละเอียดกัน เราอยากจะเล่าเกี่ยวกับโปรเจคนี้คร่าว ๆ สักหน่อย

A Breif History, 2020

  • Landing Page
  • Table of Contents
  • Features

โปรเจค LearnAlgorithm เริ่มต้นเมื่อปี 2020 ซึ่งช่วงนั้นเป็นช่วงที่เรากำลังเรียน Data Structures & Algorithm ในมหาลัยเลย

ด้วยความที่ตอนนั้นก็กำลังอินในเรื่องนี้ และก็ทำเพจแชร์เรื่องเกี่ยวกับสิ่งที่เรียนอยู่ด้วยก็เลยได้เขียนเรื่องนี้เยอะเป็นพิเศษ ได้ฝึกทำโจทย์แล้วก็ลองไปลงแข่ง รวมถึงทำคลิปแชร์ลง YouTube ด้วย (ถึงจะไม่ได้ทำต่อแล้วก็เถอะ)

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

LearnAlgorithm's Course Feedback 2020

Feedback ที่ได้จากการทำคอร์สเมื่อปี 2020

ส่วนตัวมองว่า programmer จริง ๆ แล้วไม่ใช่คนที่นั่งเขียนโค้ด แต่คือคนที่เป็น problem solver และ creator เป็นนักออกแบบและนักแก้ปัญหาคนหนึ่ง; สำหรับเราการเขียนโค้ดมันเป็นแค่ปลายทางสุดท้ายหลังจากที่เราคิดวิธีแก้ปัญหาได้แล้ว หรือออกแบบ algorithm เพื่อ solve problem ได้แล้ว

(นั่นเป็นเหตุผลว่าทำไมหลาย ๆ ครั้ง programmer อย่างเรา ๆ อาจจะใช้เวลากับ whiteboard หรือกระดาษมากกว่า code editor ด้วยซ้ำ)

ด้วยเหตุผลนี้เองมันทำให้ mission ของคอร์สนี้ไม่ได้ซับซ้อนอะไรขนาดนั้น เราอยากจะออกแบบเนื้อหาที่ช่วยให้คนอื่น (รวมถึงตัวเราเองด้วย) เป็น creator, problem-solver ที่เก่งขึ้น และเราคิดว่า data structures and algorithms มันเป็น fundamentals และ tools ที่ช่วยให้เราได้พัฒนา skills ตรงนั้น

น่าเสียดายมากที่ด้วยเหตุผลหลาย ๆ อย่าง ณ​ เวลานั้นมันทำให้เราต้องพับโปรเจคนี้เก็บเอาไว้ และหลังจากนั้นก็ไม่มีโอกาสได้กลับมาพัฒนาต่ออีกเลย

กลับมาทำใหม่, 2024

พอเวลาผ่านมาหลายปีเราก็ได้มีโอกาสได้ไปทำงานที่ต่าง ๆ ได้ลองทำโปรเจคหลาย ๆ แบบ รวมไปถึงได้มีโอกาสออกจากงานมาเป็น Indie hacker ที่ focus กับโปรเจคของตัวเองแบบเต็มตัว ได้ลองแก้ปัญหาที่หลากหลายขึ้น ทั้งในด้านที่ไม่ใช่ tech ด้วยเช่น marketing, business หรืออะไรต่าง ๆ เรารู้สึกว่าเราได้เรียนรู้อะไรมากขึ้น และมีเรื่องที่อยากจะแชร์เยอะขึ้นมากเมื่อเทียบกับ 4 ปีก่อน

เมื่อปลายปีที่ผ่านมา (August 2023) เราได้มีโอกาสขายหนึ่งในโปรเจคที่เคยทำ มันทำให้เราได้มีเวลาได้กลับมาคิดมากขึ้นว่าอยากจะทำอะไรต่อไป ซึ่ง LearnAlgorithm ก็เป็นหนึ่งในโปรเจคที่สนุกที่ได้ทำ (รวมถึงเสียดายด้วยที่ไม่ได้ทำต่อในตอนนั้น) เราเลยคิดว่ามันเป็นโอกาสที่ดีที่จะกลับมาทำโปรเจคนี้อีกครั้ง กลับมา redesign เนื้อหาใหม่ทั้งหมดให้มีความ up to date มากขึ้น

แน่นอนว่า mission ของคอร์สนี้ก็ยังเหมือนเดิม แต่ว่าก็มีบางอย่างที่ในครั้งนี้เราก็อยากจะลองทำแตกต่างจากเดิมออกไปดูบ้าง ด้านล่างนี้ก็เลยอยากจะเขียน core ideas สำคัญ ๆ ที่เราใช้ในการ design คอร์สนี้เอาไว้หน่อย เชื่อว่ามันน่าจะตอบคำถามที่หลาย ๆ คนสงสัยได้

คอร์สนี้เหมาะสำหรับใคร ?

คนที่เขียนโปรแกรมได้อย่างน้อย 1 ภาษา ที่อยากจะพัฒนา problem-solving skills และ explore ideas ในการแก้ปัญหาแบบต่าง ๆ ผ่านเนื้อหา data structures และ algorithms

(เนื้อหาทั้งหมดในคอร์สนี้จะใช้ภาษา Javascript เป็นตัวอย่างทั้งหมด)

Be More Personal

เรารู้สึกว่ามีคอร์สสอน data structures & algorithms ดี ๆ เยอะมากที่ทุกคนสามารถไปลงเรียนได้ทั้งที่เสียเงินและฟรี ยกตัวอย่างเช่น Havard CS50, MIT OpenCourseWare, FreeCodeCamp.org หรือแม้กระทั่งหนังสือดี ๆ อย่าง Grokking Algorithms (ซึ่งไว้ถ้ามีเวลาจะรวบรวม resources พวกนี้แล้วก็เขียนรีวิวของแต่ละอันอีกที) ซึ่งแน่นอนว่าเราเองก็เรียนรู้หลายอย่างมากจาก resources เหล่านี้

ดังนั้นในคอร์สนี้เราเลยอยากจะออกแบบให้มันมีความเป็น personal มากขึ้น เราอยากจะนำเสนอเนื้อหาในมุมมองในแบบของเรา ใส่ประสบการณ์หรือความเห็นส่วนตัวลงไปให้มากขึ้น ซึ่งเราเชื่อว่าคนเรียนก็คงจะได้เห็นมุมมองที่หลากหลายมากขึ้นเมื่อได้อ่านควบคู่ไปกับ resources อื่น ๆ

ถ้าให้ลอง breakdown ออกมาก็อาจจะเช่น: การใส่ opinion ต่าง ๆ ลงในในเนื้อหา, การแก้ปัญหาในด้านอื่น ๆ เช่น product design หรือ business, ประสบการณ์ในการทำงานต่าง ๆ ที่เคยเจอเกี่ยวกับ software engineering, fundamental-focused, history and etymology, creators mindset, learn and build in public และอื่น ๆ

เราคิดว่ามันคือ collection of beliefs, interests, and experiences พวกนี้หละที่มันประกอบร่างขึ้นมาเป็นคน ๆ หนึ่ง และเราอยากจะนำเสนอเนื้อหาคอร์สนี้ผ่าน collection ของตัวเราเอง

รูปแบบของเนื้อหา

สำหรับ format หลัก ๆ ของเนื้อหามีอยู่ 3 อย่างคือ:

Text-and-visual-based storytelling: เนื้อหาในคอร์สนี้จะนำเสนอผ่านรูปและตัวหนังสือทั้งหมด (ไม่มีในแง่ของ video อธิบายหรือเสียงอะไรแบบนั้น) เราอยากให้คนอ่านได้ feel เหมือนกับการอ่านหนังสือ ที่เหมือนกับการที่เราได้นั่งคุยกับตัวเอง ได้ใช้เวลา reflect และ explore ไอเดียใหม่ ๆ

Interactivity: เราพยายามออกแบบเนื้อหาให้หลาย ๆ ส่วนสามารถกดเล่นได้ ไม่ว่าจะเป็น Quiz, Problem Challenge, หรือการ visualize algorithm ต่าง ๆ เพื่อให้ผู้อ่านสามารถเข้าใจ concepts ต่าง ๆ ได้ง่ายและดียิ่งขึ้น

Get your hands dirty: ในตอนท้ายของแต่ละบทจะมี Additional Questions กับ Challenge Problem เพื่อให้ผู้อ่านได้ลองลงมือทำและได้ลอง explore ideas อื่น ๆ ที่กว้างและลึกมากขึ้น

Challenge problem at the end of each chapter

ตัวอย่าง Challenge Problem ท้ายบท; ถ้าหากว่า submit code ไม่ผ่านเกิน 3 ครั้งจะมีปุ่ม “See the solution” ขึ้นมาให้กดดูเฉลย

Free and Open

อีกอย่างที่เราตั้งใจที่จะทำในรอบนี้ก็คือ เราอยากจะเปิดเนื้อหาให้ทุกคนสามารถเข้าถึงได้ฟรี รวมไปถึงให้ทุกคนสามารถที่จะ contribute ในส่วนของเนื้อหาได้ด้วย

เรารู้สึกว่า data structures & algorithms เป็นเรื่องพื้นฐาน และมันจะเป็นอะไรที่ดีมากถ้าทุกคนสามารถเข้าถึงเนื้อหาตรงนี้ได้ เราเลยอยากให้เนื้อหาในคอร์สนี้เป็นเหมือนกับแหล่งรวมไอเดียที่ใครก็ได้สามารถเข้ามา explore

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

ดังนั้นถ้าหากว่าใครมี ideas อะไรอยากที่จะ suggest หรือมี feedback อะไรก็ตามสามารถเข้าไปเปิด Github issues ได้เลยครับ มาช่วยพัฒนาเนื้อหานี้สำหรับทุกคนไปด้วยกัน

How to create new Github issues

วิธีการสร้าง issue ใหม่ใน Github

จริง ๆ เรามีไอเดียที่น่าสนุกหลายอย่างเลยที่อยากลองทำกับโปรเจค LearnAlgorithm นี้ ซึ่งคอร์สนี้ก็เป็นหนึ่งใน milestone ที่สำคัญ ดังนั้นรอติดตามใน Facebook Page ได้เลยครับ (หรือใครมีไอเดียอยาก collaborate อะไรก็ทักมาได้เช่นกันครับ 😎)

ปัญหาคืออะไร ?

ก่อนจะไปเริ่มต้นบทถัดไปเราอยากจะมาชวนทุกคนได้ลองนั่งคิดเล่น ๆ กับตัวเองว่า “ปัญหาคืออะไร ?” เพราะมันคงจะไม่ make sense ใช่ไหมครับถ้าหากว่าเรากำลังสนใจเรื่อง problem solving โดยที่ไม่เข้าใจคำว่า “problem”

ด้านล่างนี้เป็นบทความที่เกี่ยวข้องที่อยากชวนทุกคนไปลอง explore คำตอบของคำถามนี้กันครับ

“ปัญหา” คืออะไร? มีโครงสร้างเป็นยังไง? และทำไมการเข้าใจคำ ๆ นี้ถึงสำคัญ
ปัญหาเป็นอะไรที่อยู่รอบตัวในชีวิตประจำวันของเราทุกคน แต่สิ่งที่เรามักเรียกมันจนเคยชินว่า “ปัญหา” จริง ๆ แล้วมันคืออะไร​?
“การเปลี่ยนมุมมอง” กับอัลกอริทึม Sieve of Eratosthenes
ในหลายโอกาส การแก้ปัญหา require การเปลี่ยนมุมมอง แต่การเปลี่ยนมุมมองคืออะไร ? ทำความเข้าใจไปด้วยกันผ่านปัญหาการหาค่าจำนวณเฉพาะ (prime number)
วิธีการแก้ปัญหาหรือ Solution ที่ดีเกิดขึ้นมาได้อย่างไร?
วิธีการแก้ปัญหาหรือ ‘Solution’ เกิดมาจากอะไร? Pattern นำไปสู่วิธีแก้ปัญหาที่ดีขึ้นได้อย่างไร? และเราสามารถ maximize pattern อย่างไรได้บ้าง?

สุดท้ายนี้ขอให้ทุกคนสนุกกับเนื้อหาและ enjoy problem solving ครับ~

Exercises

  1. ปัญหาคืออะไร ลองเขียนนิยามในแบบของตัวเอง ?
  2. เราจะ define ปัญหาใดปัญหาหนึ่งออกมาให้ชัดได้ยังไง ?
  3. เมื่อเรามีปัญหาที่ชัดแล้ว เราควรจะทำอะไรต่อเพื่อพาเราไปสู่ solution ที่เราต้องการ ?
  4. ถ้าหากเราคิด solution ออกมาได้แล้ว เราจะตัดสินใจจากอะไรว่า solution นี้คือ solution ที่เราควรจะเอาไป implement ต่อหรือเราควรมองหา solution ที่ดีมากขึ้นกว่านี้ ?
  5. Process ของการหานิยามของคำต่าง ๆ เป็นอย่างไร ? ลอง reflect สิ่งที่คิดออกมา

Challenge Problem

เขียน function ชื่อว่า add โดยที่รับตัวแปรมา 1 ตัวเป็นจำนวนเต็มบวก (\(n\); โดยที่ \(n > 0\)) และให้ return ผลลัพธ์ออกมาเป็นผลบวกตั้งแต่เลข 1 ถึงตัวเลขนั้น

Example 1:

Input: 3

Output: 6

Explaination: 1 + 2 + 3 = 6


Solution #1

เราสามารถแก้โจทย์ข้อนี้โดยการสร้างตัวแปร result ไว้ตัวนึง จากนั้น loop ค่าตั้งแต่ 1 ถึง n และบวกเก็บค่าลงตัวแปร result ไปเรื่อย ๆ (Naive Solution)

1
function add(n) {
2
let result = 0;
3
for (let i = 1; i <= n; ++i) {
4
result += i;
5
}
6
return result;
7
}

Solution #2

สำหรับวิธีการนี้เราจะเริ่มจากเขียนวิธีการแก้ปัญหาออกมาก่อนเพื่อดูว่ามันมี pattern อะไรที่เราสามารถนำมาสู่วิธีแก้ปัญหาที่ดีขึ้นได้ไหม เราอาจจะเริ่มจาก input น้อย ๆ ก่อนเช่น n = 10

Challenge Problem Solution #2

ถ้าหากสังเกตดูจะพบว่า ตัวหน้าสุดกับตัวท้ายสุดบวกกันได้ 11 (1 + 10) ตัวที่ 2 จากด้านหน้า กับตัวรองท้ายก็บวกกันได้ 11 (2 + 9) และตัวที่เหลือถ้าเราจับคู่เข้าด้วยกันมันก็จะบวกได้ 11 ด้วย เช่น (3 + 8), (4 + 7), (5 + 6)

หรือถ้าในกรณีที่ n เป็นเลขคี่เช่น n = 5; เราก็จะได้ (1 + 5 = 6), (2 + 4 = 6), และ 3 ซึ่งเป็นค่าที่เหลืออยู่ตรงกลางที่ไม่จับคู่กับใคร

จาก pattern ตรงนี้เราจะพบว่าในกรณีของเลขคู่ เราจะสามารถจับคู่ n + 1 ได้ n / 2 คู่ ซึ่งเราสามารถคำนวนได้โดย

(n+1)n2(n+1) * \frac{n}{2}

ส่วนกรณีที่เป็นเลขคี่ เราสามารถจับคู่ n + 1 ได้ (n - 1) / 2 คู่ และบวกกับค่าตรงกลางที่ไม่จับกับตัวไหนเลยก็คือ (n + 1) / 2 ซึ่งสามารถสรุปสมการออกมาได้เป็น

(n+1)n12+n+12=(n+1)n2(n+1) * \frac{n - 1}{2} + \frac{n + 1}{2} = (n+1) * \frac{n}{2}

เราสามารถเขียนเป็นสมการได้เป็น

add(n)=n2(1+n)add(n) = \frac{n}{2} * (1 + n)

1
function add(n) {
2
return (n + 1) * (n / 2);
3
}