summaryrefslogtreecommitdiffstats
path: root/2021/20/code.tl
blob: dcc493389f1882a099b028356ba34e65edb6336a (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
(defvarl h2b (relate ".#" #(0 1)))

(defvarl b2h ".#")

(defstruct ctx ()
  alg
  (hash (hash))
  grid
  (min-x 0) (min-y 0)
  (max-x 0) (max-y 0)
  toggle

  (:postinit (me)
    (if (nzerop [me.alg 0])
      (set me.toggle 0))
    (each ((line me.grid)
           (y 0))
      (each ((bit line)
             (x 0))
        (set [me.hash x..y] [h2b bit])
        (upd me.max-x (max x))
        (upd me.max-y (max y)))))

  (:method lambda (me x y)
    (or [me.hash x..y]
        me.toggle
        0))

  (:method lambda-set (me x y nv)
    (set [me.hash x..y] nv)
    (upd me.max-x (max x))
    (upd me.min-x (min x))
    (upd me.max-y (max y))
    (upd me.min-y (min y)))

  (:method print (me stream pretty-p)
    (each ((y me.min-y..(succ me.max-y)))
      (each ((x me.min-x..(succ me.max-x)))
        (put-char [b2h [me x y]] stream))
      (put-line : stream))))

(defmeth ctx step (me)
  (let ((nme (copy me)))
    (set nme.hash (hash))
    (each-prod ((y (pred me.min-y)..(ssucc me.max-y))
                (x (pred me.min-x)..(ssucc me.max-x)))
      (let* ((x- (pred x)) (x+ (succ x))
             (y- (pred y)) (y+ (succ y))
             (bits (flow (vec [me x- y-] [me x y-] [me x+ y-]
                              [me x- y]  [me x y]  [me x+ y]
                              [me x- y+] [me x y+] [me x+ y+])
                     (poly 2))))
        (set [nme x y] [me.alg bits])))
    (replace-struct me nme)
    (upd me.toggle [iff true (op - 1)])
    me))

(defun read-input (: (name "input"))
  (flow (file-get-lines name)
    (match (@alg "" . @grid) @1
      (new ctx
           alg [mapcar h2b alg]
           grid grid))))

;; answers; 5291, 16665.
(defun solve (steps : (name :))
  (flow name
    (read-input)
    (dotimes (i steps @1)
      (put-line `step @i`)
      @1.(step))
    .hash
    (count-if plusp @1 cdr)))