summaryrefslogtreecommitdiffstats
path: root/2021/11/code.tl
diff options
context:
space:
mode:
Diffstat (limited to '2021/11/code.tl')
-rw-r--r--2021/11/code.tl78
1 files changed, 78 insertions, 0 deletions
diff --git a/2021/11/code.tl b/2021/11/code.tl
new file mode 100644
index 0000000..9dc724b
--- /dev/null
+++ b/2021/11/code.tl
@@ -0,0 +1,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))))