summaryrefslogtreecommitdiffstats
path: root/2021/11/code.tl
blob: 9dc724b5908e22cab3b00d1497c9fa3c0810a977 (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
76
77
78
(defstruct board ()
  w h a s

  (:postinit (bo)
    (set bo.s (* bo.w bo.h)))

  (:method count-flashes (bo)
    (sum bo.a (op countql #\0)))

  (:method all-flash (bo)
    (eql bo.s bo.(count-flashes)))

  (:method lambda (me x y)
    (if (or (minusp x)
            (minusp y)
            (<= me.w x)
            (<= me.h y))
      #\0
      [[me.a y] x]))

  (:method lambda-set (me x y nv)
    (unless (or (minusp x)
                (minusp y)
                (<= me.w x)
                (<= me.h y))
      (set [[me.a y] x] nv))))

(defmacro forxy (x y bo . body)
  ^(each-prod ((,y 0..(qref ,bo h))
               (,x 0..(qref ,bo w)))
     ,*body))

(defmacro incnz (place)
  (with-gensyms (p)
    ^(placelet ((,p (read-once ,place)))
       (if (eql #\0 ,p) #\0 (inc ,p)))))

(defmacro mincnz (. places)
  ^(progn ,*(mapcar (ret ^(incnz ,@1)) places)))

(defun read-board-file (: (name "input"))
  (flow (file-get-lines name)
    vec-list
    (new board
         h (len @1)
         w (len (first @1))
         a @1)))

(defmeth board step (bo)
  (forxy x y bo
    (inc [bo x y]))
  (let ((flashed t))
    (while flashed
      (zap flashed)
      (forxy x y bo
        (when (> [bo x y] #\9)
          (set flashed t
               [bo x y] #\0)
          (let ((x- (pred x)) (x+ (succ x))
                (y- (pred y)) (y+ (succ y)))
            ;; "multi increment, from non-zero"
            (mincnz [bo x- y-] [bo x  y-] [bo x+ y-]
                    [bo x- y]             [bo x+ y]
                    [bo x- y+] [bo x  y+] [bo x+ y+]))))))
  bo)

(defun solve-part-one (: (name "input"))
  (let ((bo (read-board-file name))
        (tf 0))
    (dotimes (i 100 tf)
      (inc tf bo.(step).(count-flashes)))))

(defun solve-part-two (: (name "input"))
  (for ((bo (read-board-file name))
        (i 0))
       ((not bo.(all-flash)) i)
       (bo.(step)
        (inc i))))