summaryrefslogtreecommitdiffstats
path: root/2021/18/code2.tl
blob: 58e2e3232c474dbbb88abeeb2f95668079556719 (plain)
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
71
72
73
74
75
(defun read-string (str)
  (flow str (mapcar (relate '(#\[ #\] #\,) '(#\( #\) #\space))) read))

(defun read-input (: (name "input"))
  (flow name file-get-lines (mapcar read-string)))

(defun ladd (n sn)
  (tree-case sn
    ((a b) ^(,(ladd n a) ,b))
    (m (+ n m))))

(defun radd (sn n)
  (tree-case sn
    ((a b) ^(,a ,(radd b n)))
    (m (+ m n))))

(defun explode (sn)
  (tree-case sn
    ((((((a b) x) y) z) w) ^((((0 ,(ladd b x)) ,y) ,z) ,w))
    (((((x (a b)) y) z) w) ^((((,(radd x a) 0) ,(ladd b y)) ,z) ,w))
    ((((y ((a b) x)) z) w) ^(((,(radd y a) (0 ,(ladd b x))) ,z) ,w))
    ((((y (x (a b))) z) w) ^(((,y (,(radd x a) 0)) ,(ladd b z)) ,w))
    (((z (((a b) x) y)) w) ^((,(radd z a) ((0 ,(ladd b x)) ,y)) ,w))
    (((z ((x (a b)) y)) w) ^((,z ((,(radd x a) 0) ,(ladd b y))) ,w))
    (((z (y ((a b) x))) w) ^((,z (,(radd y a) (0 ,(ladd b x)))) ,w))
    (((z (y (x (a b)))) w) ^((,z (,y (,(radd x a) 0))) ,(ladd b w)))
    ((w ((((a b) x) y) z)) ^(,(radd w a) (((0 ,(ladd b x)) ,y) ,z)))
    ((w (((x (a b)) y) z)) ^(,w (((,(radd x a) 0) ,(ladd b y)) ,z)))
    ((w ((y ((a b) x)) z)) ^(,w ((,(radd y a) (0 ,(ladd b x))) ,z)))
    ((w ((y (x (a b))) z)) ^(,w ((,y (,(radd x a) 0)) ,(ladd b z))))
    ((w (z (((a b) x) y))) ^(,w (,(radd z a) ((0 ,(ladd b x)) ,y))))
    ((w (z ((x (a b)) y))) ^(,w (,z ((,(radd x a) 0) ,(ladd b y)))))
    ((w (z (y ((a b) x)))) ^(,w (,z (,(radd y a) (0 ,(ladd b x))))))
    ((w (z (y (x (a b))))) ^(,w (,z (,y (,(radd x a) 0)))))
    (else else)))

(defun splt (sn)
  (tree-case sn
    ((a b)
     (let ((as (splt a))
           (bs (splt b)))
       (cond
         ((neq a as) ^(,as ,b))
         ((neq b bs) ^(,a ,bs))
         (t sn))))
    (m (if (< m 10)
         m
         (let* ((x (trunc m 2))
                (y (- m x)))
           ^(,x ,y))))))

(defun reduce (sn)
  (let (sn*)
    (while* (neq sn* sn)
      (while* (neq sn* sn)
        (shift sn* sn (explode sn)))
      (shift sn* sn (splt sn)))
    sn))

(defun add (sn0 sn1)
  (reduce (list sn0 sn1)))

(defun mag (sn)
  (tree-case sn
    ((a b) (+ (* 3 (mag a)) (* 2 (mag b))))
    (m m)))

(defun solve-one (: (name :))
  (flow name read-input (reduce-left add) mag))

(defun solve-two (: (name :))
  (flow name read-input (comb @1 2)
    (mappend [juxt [chain [apf add] mag]
                   [chain [apf [flipargs add]] mag]])
    find-max))