Login
7 branches 0 tags
Ben (X13/Arch) Simplified things a little 0643405 9 days ago 1260 Commits
nujel / tests / fast / day14.nuj
#!/usr/bin/env nujel

(defn polymer/read (line)
      (def eles {})
      (def pairs {})
      (dotimes (i (:length line))
               (def key-a (:symbol (:cut line i (+ i 1))))
               (if (:has? eles key-a)
                   (tree/++ eles key-a)
                   (set! eles key-a 1))
               (when (< i (- (:length line) 1))
                     (def key-b (:symbol (:cut line i (+ i 2))))
                     (if (:has? pairs key-b)
                         (tree/++ pairs key-b)
                         (set! pairs key-b 1))))
      {:pairs pairs :eles eles :combinations '()})

(defn combination/parse (recipe last-recipe)
      (def source (:symbol (car recipe)))
      (def new    (:symbol (cadr recipe)))
      (def new-α (:symbol (cat (:cut (car recipe) 0 1) (cadr recipe))))
      (def new-β (:symbol (cat (cadr recipe) (:cut (car recipe) 1 2))))
      (fn (α Ω)
          (def count (int (or (ref (ref α :pairs) source) 0)))
        (tree/+= (ref Ω :eles) new count)
        (tree/+= (ref Ω :pairs) source (- count))
        (tree/+= (ref Ω :pairs) new-α count)
        (tree/+= (ref Ω :pairs) new-β count)
        (if (lambda? last-recipe) (last-recipe α Ω) Ω)))

(defn combination/add (state recipe)
      (set! state :combinations (combination/parse recipe (ref state :combinations))))

(defn combinations/read (state lines)
      (for-each lines (fn (line) (combination/add state (split line " -> "))))
      state)

(defn state/read (fn)
      (def input-raw (split (file/read fn) "\n"))
      (def state (polymer/read (car input-raw)))
      (combinations/read state (cddr input-raw)))

(defn state/dup (α)
      {:combinations (ref α :combinations) :pairs (:clone (ref α :pairs)) :eles (:clone (ref α :eles))})

(defn state/run/once (α)
      ((ref α :combinations) α (state/dup α)))

(defn state/run/many (α steps)
      (if (<= steps 0) α
          (state/run/many (state/run/once α)
                          (- steps 1))))

(defn result (state)
      (- (apply max (:values (ref state :eles)))
         (apply min (:values (ref state :eles)))))

(def state (state/read "tests/fast/day14.dat"))
(def p1-state (state/run/many state 10))
(def res-p1 (result p1-state))
(when (not= res-p1 2010)
      (throw (list :wrong-result "Wrong Part 1 result" res-p1)))
(def res-p2 (result (state/run/many p1-state 30)))
(when (not= res-p2 2437698971143)
      (throw (list :wrong-result "Wrong Part 2 result" res-p2)))
(return :success)