application/octet-stream
•
3.35 KB
•
101 lines
#!/usr/bin/env nujel
(defn snail/read-line (line)
(read/single (join (split line ",") " . ")))
(defn snail/parse-list (l d)
(cond ((nil? l) #nil)
((int? l) @(:v l))
(#t @(:r (snail/parse-list (cdr l)) :l (snail/parse-list (car l))))))
(defn snail/read (line)
(snail/parse-list (snail/read-line line)))
(defn snail/int? (l)
(and l (ref l :v)))
(defn snail->str (l)
(cond ((snail/int? l) (string (ref l :v)))
(#t (cat "(" (snail->str (ref l :l)) "," (snail->str (ref l :r)) ")"))))
(defn snail/find (root needle as bs)
(def last #nil)
(defn rec (t root needle)
(cond ((snail/int? t) (set! last t) #f)
((= needle t) last)
(#t (or (rec (ref t as) root needle)
(rec (ref t bs) root needle)))))
(rec root root needle))
(defn snail/find/previous (root needle)
(snail/find root needle :l :r))
(defn snail/find/next (root needle)
(snail/find root needle :r :l))
(defn snail/explode (t root)
(def p (snail/find/previous root t))
(when p (tree/+= p :v (ref (ref t :l) :v)))
(def n (snail/find/next root t))
(when n (tree/+= n :v (ref (ref t :r) :v)))
(-> t
(tree/set! :v 0)
(tree/set! :l #nil)
(tree/set! :r #nil)))
(defn snail/split (t root)
(def lv (div/int (ref t :v) 2))
(-> t
(tree/set! :l @(:v lv))
(tree/set! :r @(:v (- (ref t :v) lv)))
(tree/set! :v #nil)))
(defn snail/explode/maybe (t root d)
(cond ((snail/int? t) #f)
((>= d 4) (snail/explode t root))
((snail/explode/maybe (ref t :l) root (+ 1 d)) #t)
(#t (snail/explode/maybe (ref t :r) root (+ 1 d)))))
(defn snail/split/maybe (t root d)
(cond ((snail/int? t) (and (>= (ref t :v) 10)
(snail/split t root) #t))
((snail/split/maybe (ref t :l) root (+ 1 d)) #t)
(#t (snail/split/maybe (ref t :r) root (+ 1 d)))))
(defn snail/reduce (t)
(while (or (snail/explode/maybe t t 0)
(snail/split/maybe t t 0))) t)
(defn snail/add (a b)
(snail/reduce @(:l a :r b)))
(defn snail/sum (lines)
(def vals (map (split lines "\n") snail/read))
(reduce (cdr vals) snail/add (car vals)))
(defn snail/mag (t)
(cond ((snail/int? t) (ref t :v))
(#t (+ (* (snail/mag (ref t :l)) 3)
(* (snail/mag (ref t :r)) 2)))))
(defn snail/find-biggest (lines)
(def vals (apply array/new (split lines "\n")))
(def cmax 0)
(dotimes (a 100)
(dotimes (b 100)
(when (not= a b)
(def cs (snail/add (snail/read (array/ref vals a)) (snail/read (array/ref vals b))))
(set! cmax (max cmax (snail/mag cs)))
(def cs (snail/add (snail/read (array/ref vals b)) (snail/read (array/ref vals a))))
(set! cmax (max cmax (snail/mag cs))))))
cmax)
(def res-p1 (snail/mag (snail/sum (file/read "tests/slow/day18.input"))))
(when (not= res-p1 3725)
(throw (list :wrong-result "Wrong result" res-p1)))
(def res-p2 (snail/find-biggest (file/read "tests/slow/day18.input")))
(when (not= res-p2 4832)
(throw (list :wrong-result "Wrong result" res-p2)))
(return :success)