(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))))