|
| 1 | +(eval-when (:compile-toplevel :load-toplevel :execute) |
| 2 | + (ql:quickload "cl-ppcre" :silent t)) |
| 3 | + |
| 4 | +(defun parse-ints (s) |
| 5 | + (mapcar #'parse-integer (ppcre:all-matches-as-strings "-?\\d+" s))) |
| 6 | + |
| 7 | +(defun parse-line (s) |
| 8 | + (let ((on? (string= (subseq s 0 2) "on"))) |
| 9 | + (cons on? (parse-ints s)))) |
| 10 | + |
| 11 | +(defun make-cube-dims (coords) |
| 12 | + (loop for (_ x1 x2 y1 y2 z1 z2) in coords |
| 13 | + nconcing (list (1- x1) x1 (1+ x1) (1- x2) x2 (1+ x2)) into xs |
| 14 | + nconcing (list (1- y1) y1 (1+ y1) (1- y2) y2 (1+ y2)) into ys |
| 15 | + nconcing (list (1- z1) z1 (1+ z1) (1- z2) z2 (1+ z2)) into zs |
| 16 | + finally (return |
| 17 | + (mapcar (lambda (es) |
| 18 | + (let ((list (sort (remove-duplicates es) #'<))) |
| 19 | + (make-array (length list) :initial-contents list))) |
| 20 | + (list xs ys zs))))) |
| 21 | + |
| 22 | +(defun toggle (cubes cube-dims coords) |
| 23 | + (destructuring-bind ((xs ys zs) (on? x1 x2 y1 y2 z1 z2)) (list cube-dims coords) |
| 24 | + (loop for x from (position x1 xs) to (position x2 xs) |
| 25 | + do (loop for y from (position y1 ys) to (position y2 ys) |
| 26 | + do (loop for z from (position z1 zs) to (position z2 zs) |
| 27 | + do (setf (aref cubes x y z) (if on? 1 0))))))) |
| 28 | + |
| 29 | +(defun on-count (cubes cube-dims) |
| 30 | + (destructuring-bind ((xs ys zs) (x-dim y-dim z-dim)) (list cube-dims (array-dimensions cubes)) |
| 31 | + (loop for x from 1 below (1- x-dim) |
| 32 | + summing (loop for y from 1 below (1- y-dim) |
| 33 | + summing (loop for z from 1 below (1- z-dim) |
| 34 | + for on? = (= (aref cubes x y z) 1) |
| 35 | + if on? |
| 36 | + summing (* (- (aref xs (1+ x)) (aref xs x)) |
| 37 | + (- (aref ys (1+ y)) (aref ys y)) |
| 38 | + (- (aref zs (1+ z)) (aref zs z)))))))) |
| 39 | + |
| 40 | +(defun part-1 () |
| 41 | + (let* ((input (uiop:read-file-lines "input.txt")) |
| 42 | + (coords (mapcar #'parse-line (subseq input 0 20))) |
| 43 | + (cube-dims (make-cube-dims coords)) |
| 44 | + (cubes (make-array (mapcar #'length cube-dims) :initial-element 0 :element-type 'bit))) |
| 45 | + (loop for c in coords |
| 46 | + do (toggle cubes cube-dims c) |
| 47 | + finally (return (on-count cubes cube-dims))))) |
| 48 | + |
| 49 | +; 9.5 min runtime, but it works. |
| 50 | +(defun part-2 () |
| 51 | + (let* ((input (uiop:read-file-lines "input.txt")) |
| 52 | + (coords (mapcar #'parse-line input)) |
| 53 | + (cube-dims (make-cube-dims coords)) |
| 54 | + (cubes (make-array (mapcar #'length cube-dims) :initial-element 0 :element-type 'bit))) |
| 55 | + (loop for c in coords |
| 56 | + do (toggle cubes cube-dims c) |
| 57 | + finally (return (on-count cubes cube-dims))))) |
0 commit comments