about summary refs log tree commit diff
path: root/day18.clj
blob: 2b41d98eb05e913b636c8af357d67c13af06e969 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
(ns org.vuxu.aoc2021.day18
  (:require [clojure.string :as str]))

(def data
  (->> (slurp "day18")
       str/split-lines
       (map clojure.edn/read-string)))

(defn add-leftmost [n t]
  (if (number? t)
    (+ n t)
    [(add-leftmost n (first t)) (second t)]))

(defn add-rightmost [n t]
  (if (number? t)
    (+ n t)
    [(first t) (add-rightmost n (second t))]))

(defn explode2 [depth t]
  (if (number? t)
    nil
    (let [[l r] t]
      (if (= depth 4)
        [0 l r]
        (if-let [[l' ln rn] (explode2 (inc depth) l)]
          [[l' (add-leftmost rn r)] ln 0]
          (if-let [[r' ln rn] (explode2 (inc depth) r)]
            [[(add-rightmost ln l) r'] 0 rn]))))))

(defn explode [t]
  (first (explode2 0 t)))

(defn split [t]
  (if (number? t)
    (if (>= t 10)
      [(long (Math/floor (/ t 2)))
       (long (Math/ceil (/ t 2)))])
    (let [[l r] t]
      (if-let [l' (split l)]
        [l' r]
        (if-let [r' (split r)]
          [l r'])))))

(defn reduc [t]
  (if-let [t' (explode t)]
    (recur t')
    (if-let [t' (split t)]
      (recur t')
      t)))

(defn add [x y]
  (reduc (conj [x] y)))

(defn mag [t]
  (if (number? t)
    t
    (+ (* 3 (mag (first t)))
       (* 2 (mag (second t))))))

(def part1
  (mag (reduce add data)))
;; => 4173

(def part2
  (apply max
         (for [x data
               y data
               :when (not= x y)]
           (mag (add x y)))))
;; => 4706