adventofcode2022

My solutions for Advent of Code 2022
Log | Files | Refs

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)