day18.lisp (2749B)
1 (defpackage #:adventofcode2022/day18 2 (:use #:cl #:adventofcode2022) 3 (:import-from #:queues 4 #:make-queue 5 #:qpush 6 #:qpop 7 #:qsize)) 8 (in-package #:adventofcode2022/day18) 9 10 (defparameter *sides* (list (list 1 0 0) 11 (list 0 1 0) 12 (list 0 0 1) 13 (list -1 0 0) 14 (list 0 -1 0) 15 (list 0 0 -1))) 16 17 (defun coord+ (a b) 18 (loop for i-1 in a 19 for i-2 in b 20 collect (+ i-1 i-2))) 21 22 (defun coord-compare (a b test) 23 (loop for i-1 in a 24 for i-2 in b 25 always (funcall test i-1 i-2))) 26 27 (defun task1 (inputs) 28 (let ((map (make-hash-table :test 'equal))) 29 (loop for input in inputs 30 do (setf (gethash input map) t)) 31 (loop for coord being the hash-key of map 32 sum (loop for side in *sides* 33 when (not (gethash (coord+ coord side) map)) 34 sum 1)))) 35 36 (defun task2 (inputs) 37 (multiple-value-bind (map min-pos max-pos) 38 (loop with map = (make-hash-table :test 'equal) 39 for input in inputs 40 do (setf (gethash input map) t) 41 minimize (car input) into min-x 42 minimize (cadr input) into min-y 43 minimize (caddr input) into min-z 44 maximize (car input) into max-x 45 maximize (cadr input) into max-y 46 maximize (caddr input) into max-z 47 finally (return (values map 48 (list min-x min-y min-z) 49 (list max-x max-y max-z)))) 50 (setf min-pos (coord+ min-pos '(-1 -1 -1))) 51 (setf max-pos (coord+ max-pos '(1 1 1))) 52 (loop with queue = (make-queue :simple-queue) 53 with visited = (make-hash-table :test 'equal) 54 with surface-area = 0 55 initially (qpush queue min-pos) 56 while (> (qsize queue) 0) 57 for coord = (qpop queue) 58 do (loop for side in *sides* 59 for side-coord = (coord+ coord side) 60 do (if (gethash side-coord map) 61 (incf surface-area) 62 (when (and (not (gethash side-coord visited)) 63 (coord-compare side-coord min-pos #'>=) 64 (coord-compare side-coord max-pos #'<=)) 65 (qpush queue side-coord) 66 (setf (gethash side-coord visited) t)))) 67 finally (return surface-area)))) 68 69 (define-day 18 70 (:translate-input (lambda (line) 71 (mapcar #'parse-integer (uiop:split-string line :separator '(#\,))))) 72 #'task1 73 #'task2)