day 18, part 1, the simple one

This commit is contained in:
efim 2022-12-22 19:49:43 +00:00
parent 01d5c300d6
commit 643bba2464
4 changed files with 3061 additions and 0 deletions

2893
day18-input.txt Normal file

File diff suppressed because it is too large Load Diff

107
day18-scratch.lisp Normal file
View File

@ -0,0 +1,107 @@
;; ;; https://adventofcode.com/2022/day/18
;; so, 1x1x1 cubes on grid, given by x-y-z coords,
;; so each line is 1 cube.
;;
;; my guess is 1,1,1 is cube [0,1]x[0,1]x[0,1]
;; and 2,1,1 is cube [1,2]x[0,1]x[0,1]
;;
;; for cubes to have "joint" side - two dimentions should be totally same
;;
;; so, could do what? put into 3d array?
;; have 3 hash tables?
;;
;; allright, looking at discussions already.
;; i "could" consider these as graph nodes, but what would be the edges?
;;
;; the 3d array would be 'connectivity' matrix
;; then i'd want what ? go through all the nodes.
;; and for each node know how many neighbors it has.
;; that would directly transform into how many sides are open.
;; ok, i guess
(defparameter *day-18-test-input*
(mapcar
(lambda (line)
(mapcar #'parse-integer (cl-ppcre:split "," line)))
(uiop:read-file-lines "day18-test.txt")))
(setq *day-18-test-input* (coords-from-input "day18-test.txt"))
;; so. init array and fill with nodes
;; figure out maximal values?
(loop
for (x y z) in *day-18-test-input*
maximize x into xs
maximize y into ys
maximize z into zs
finally (return (list xs ys zs)))
;; => (3 3 6)
(defparameter *day-18-test-graph-connectivity*
(make-array '(4 4 7) :initial-element 0))
;; fill the array with nodes
(loop
for (x y z) in *day-18-test-input*
do (setf (aref *day-18-test-graph-connectivity* x y z) 1))
;; and now would have to do full scan? that's not very fun =/
;; well, it's not quite what a connectivity matrix is, isn't it?
;; connectivity has 1 in (i j) if from node i to node j there's edge
;; and it current case we have only 1 unit length connections.
;; here's that
(neighbors-for '(2 2 2) *day-18-test-graph-connectivity*)
(neighbors-for '(1 1 1) *day-18-test-graph-connectivity*)
(neighbors-for '(2 3 5) *day-18-test-graph-connectivity*)
;; and now to iterate over all of the array?
;; how'd i do safer aref?
;; well, i guess ok.
(apply #'aref *day-18-test-graph-connectivity* '(2 3 5))
;; this is first time i see something like this
;; how to use that correctly though?
;; so, last value must be a list, and all values are appended
;; so just numbers and nil in the end would work?
;; and more importatntly passing array as just self works.
;; and splitting points as two lists should work, right?
(apply #'aref *day-18-test-graph-connectivity* 2 3 '(5))
;; no, it doesn't, only one by one with last thing as list
;; now loop over all elements as ask amount of neighbors and sum 6-neighbors?
(loop for x from 0 to 3 sum
(loop for y from 0 to 3 sum
(loop for z from 0 to 6
when (= 1 (aref *day-18-test-graph-connectivity* x y z))
summing (- 6
(length (neighbors-for (list x y z)
*day-18-test-graph-connectivity*)))
;; into the-sum
;; collecting (list x y z)
;; into nodes
;; finally (return (list the-sum nodes))
)
))
;; => (42 ((0 0 0) (0 0 1) (0 0 2) (0 0 3) (0 0 4) (0 0 5) (0 0 6)))
(neighbors-for '(2 2 2) *day-18-test-graph-connectivity*)
;; well it's not quite so pliant to use multiple 'summing 'collecting 'max 'into
;; when working with nested loops then
;; for those cases DO macro? =C
(count-open-sides *day-18-test-graph-connectivity*)
;; now for my own input?
(defparameter *day-18-input-coords* nil)
(setq *day-18-input-coords*
(coords-from-input "day18-input.txt"))
(defparameter *day-18-input-connectivity*
(make-array (find-maxes *day-18-input-coords*) :initial-element 0))

13
day18-test.txt Normal file
View File

@ -0,0 +1,13 @@
2,2,2
1,2,2
3,2,2
2,1,2
2,3,2
2,2,1
2,2,3
2,2,4
2,2,6
1,2,5
3,2,5
2,1,5
2,3,5

48
day18.lisp Normal file
View File

@ -0,0 +1,48 @@
;; https://adventofcode.com/2022/day/18
(ql:quickload 'cl-ppcre)
(defun coords-from-input (file-name)
(mapcar
(lambda (line)
(mapcar #'parse-integer (cl-ppcre:split "," line)))
(uiop:read-file-lines file-name)))
(defun find-maxes (all-coords)
(loop
for (x y z) in all-coords
maximize (1+ x) into xs
maximize (1+ y) into ys
maximize (1+ z) into zs
finally (return (list xs ys zs))) )
(defun fill-connectivity-array (all-coords connectivity-matrix)
(loop
for (x y z) in all-coords
do (setf (aref connectivity-matrix x y z) 1)))
(defun neighbors-for (coords connectivity-matrix)
(labels ((coords-fit (potential-point)
(loop for i from 0 to 2
always (and (< (nth i potential-point)
(array-dimension connectivity-matrix i))
(>= (nth i potential-point) 0)))))
(loop
for deltas in `((1 0 0) (-1 0 0)
(0 1 0) (0 -1 0)
(0 0 1) (0 0 -1))
for neighbor = (mapcar #'+ coords deltas)
when
(and (coords-fit neighbor)
(= 1 (apply #'aref connectivity-matrix neighbor)))
collect neighbor)))
(defun count-open-sides (connectivity-matrix)
(destructuring-bind (n m k)
(array-dimensions connectivity-matrix)
(loop for x from 0 below n sum
(loop for y from 0 below m sum
(loop for z from 0 below k
when (= 1 (aref connectivity-matrix x y z))
summing (- 6
(length (neighbors-for (list x y z) connectivity-matrix))))))))