Skip to content

Instantly share code, notes, and snippets.

@erdos
Created December 18, 2021 06:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erdos/797f5a63016b919e43d619fb3a957b49 to your computer and use it in GitHub Desktop.
Save erdos/797f5a63016b919e43d619fb3a957b49 to your computer and use it in GitHub Desktop.
Advent Of Code 2021 Day 18 in Clojure with zippers
(require '[clojure.zip :as zip])
(def input (slurp "day18.txt"))
(def lines (vec (s/split-lines input)))
(def vecs (map read-string lines))
(defn magnitude [x]
(if (number? x)
x
(+ (* 3 (magnitude (first x))) (* 2 (magnitude (second x))))))
(defn split-regular [x] (assert (integer? x))
[(int (/ x 2)) (int (Math/ceil (/ x 2)))])
(defn depth [z] (if (nil? z) -1 (inc (depth (zip/up z)))))
(defn next-leaf [z]
(when z
(if-let [zr (zip/right z)]
(loop [zd zr]
(if (number? (zip/node zd))
zd
(recur (zip/down zd))))
(recur (zip/up z)))))
(defn prev-leaf [z]
(when z
(if-let [zr (zip/left z)]
(loop [zd zr]
(if (number? (zip/node zd))
zd
(recur (zip/rightmost (zip/down zd)))))
(recur (zip/up z)))))
(defn explode-4-deep [x]
(loop [zipper (zip/vector-zip x)]
(when-not (zip/end? zipper)
; (println :! (zip/node zipper))
(let [depth (depth zipper)]
(if (and (= 4 depth) (vector? (zip/node zipper)))
(let [[left right] (zip/node zipper)]
(-> (zip/replace zipper 0)
((fn [zipper]
(if-let [pz (prev-leaf zipper)]
(next-leaf (zip/edit pz + left)) ;; return to zero
zipper)))
((fn [zipper]
(if-let [nz (next-leaf zipper)]
(zip/edit nz + right)
zipper)))
(zip/root)))
(recur (zip/next zipper)))))))
(defn split-leftmost-10 [x]
(if (vector? x)
(if-let [ls (split-leftmost-10 (first x))]
[ls (second x)]
(if-let [rs (split-leftmost-10 (second x))]
[(first x) rs]))
(when (>= x 10) (split-regular x))))
(defn reduced-result [x]
(let [fx (or (explode-4-deep x)
(split-leftmost-10 x)
x)]
(if (= x fx) fx
(recur fx))))
(defn addition [a b] (reduced-result [a b]))
(println :first-answer (magnitude (reduce addition vecs)))
(println :second-answer
(apply max (for [a vecs b vecs :when (not= a b)]
(magnitude (addition a b)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment