DEV Community

Phondanai
Phondanai

Posted on

Day 1 - Advent of Code 2021 ด้วย Clojure

ในโพสต์นี้จะลองใช้ Clojure แก้โจทย์ของ Advent of Code ปี 2021 Day 1

โจทย์ (part 1)

โจทย์ต้องการทราบว่าจำนวนครั้งที่ค่าเพิ่มขึ้น มีกี่ครั้ง โดยจะมี input มาให้ (ตั้งชื่อไว้ว่า input.txt) จากตัวอย่างในรูปคือ เพิ่มขึ้น 7 ครั้ง
ตัวอย่างคำตอบคือ 7

  1. อันดับแรก อ่าน input และแปลงให้เป็นตัวเลข, เพราะอ่านมาจาก text ไฟล์
(def input-part-1
  (map #(Integer/parseInt %) 
    (clojure.string/split-lines 
      (slurp "input.txt")))) 
Enter fullscreen mode Exit fullscreen mode
  1. เทียบค่าในแต่ละคู่ว่าเพิ่มขึ้นหรือลดลง ซึ่งจากในตัวอย่างในรูป จะเทียบไปทีละค่า, เราสามารถใช้ partition จับคู่ในแบบที่เราต้องการได้
(partition 2 1 (range 10))
; ((0 1) (1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8) (8 9))
Enter fullscreen mode Exit fullscreen mode

เพราะฉะนั้น โค้ดในส่วนนี้คือ

(partition 2 1 input-part-1)
Enter fullscreen mode Exit fullscreen mode

ทำการเปรียบเทียบค่า โดยใช้ < เพื่อเทียบว่าค่าของตัวแรกน้อยกว่าตัวที่สองในคู่หรือไม่ โดยใช้ร่วมกับ map และ apply

(map #(apply < %)
  (partition 2 1 input-part-1))
; ผลลัพธ์จะได้ (true false true false ....)
Enter fullscreen mode Exit fullscreen mode
  1. จากนั้น นับจำนวนของค่า true ก็จะได้คำตอบของ part 1
(count
  (filter identity (map #(apply < %)
    (partition 2 1 input-part-1))))
Enter fullscreen mode Exit fullscreen mode

เสร็จแล้วสำหรับ part 1

โจทย์ (part 2)

โจทย์ต้องการทราบจำนวนครั้งที่ค่าเพิ่มขึ้นเหมือนเดิม แต่ที่ต่างออกไปคือมี sliding window, โจทย์กำหนดมาคือ sliding window เท่ากับ 3 แปลว่า ต้องคำนวนค่าตัวเลขสามตัว แล้วนำมารวมกัน ทำแบบนี้ไปจนครบ แล้วจึงนำมาเปรียบเทียบกัน ดังในตัวอย่าง

แสดงค่า sliding window

ค่าของ A ได้มาจากค่าที่ 1-3, B ได้มาจาก 2-4 ,C ... ไปจนครบ input
ตัวอย่างคำตอบคือ 5

  1. เราสามารถใช้ partition ได้เช่นเดิม ต่างกันที่จำนวนในแต่ละกลุ่ม (กลุ่มละ 3 ค่า) เช่น
(partition 3 1 [199 200 208 210 200 207 240 269 260 263])
; ((199 200 208) (200 208 210) (208 210 200) (210 200 207) (200 207 240) (207 240 269) (240 269 260) (269 260 263))

Enter fullscreen mode Exit fullscreen mode
  1. เมื่อได้กลุ่มของค่ามาแล้ว ในแต่ละกลุ่มก็เอาค่าเหล่านั้นมาบวกกัน
(map #(reduce + %)
  (partition 3 1 [199 200 208 210 200 207 240 269 260 263]))
; (607 618 618 617 647 716 769 792)
Enter fullscreen mode Exit fullscreen mode
  1. จากตรงนี้เราก็สามารถใช้วิธีของ part 1 ในการหาคำตอบได้แล้ว
(count
  (filter identity (map #(apply < %)
    (partition 2 1 
      (map #(reduce + %)
        (partition 3 1 [199 200 208 210 200 207 240 269 260 263]))))))
; 5
Enter fullscreen mode Exit fullscreen mode

ไม่รู้ว่าจะมี Day 2 รึเปล่านะ เพราะตอนนี้ทำได้แค่ Day 1 น่ะ :P

Top comments (0)