167 lines
6.0 KiB
Common Lisp
167 lines
6.0 KiB
Common Lisp
;; ;; 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))
|
|
(fill-connectivity-array *day-18-input-coords* *day-18-input-connectivity*)
|
|
|
|
(count-open-sides *day-18-input-connectivity*)
|
|
|
|
;; now. how could i only include surface area
|
|
;; did i need to model points as what?
|
|
;;
|
|
;; well, i could start with 0th layer. there's no stone there, only air
|
|
;; and start filling with 2
|
|
;; then count for all points as previously, but only neighbors which are 2
|
|
;; i guess
|
|
|
|
;; so. start at '(0 0 0)
|
|
;; then get neighbors, filter those that are 0
|
|
;; put into queue / list - actually dfs is good enough, so just recurse?
|
|
|
|
(point-at-is '(0 0 0) *day-18-test-graph-connectivity* 0)
|
|
(point-at-is '(0 0 0) *day-18-test-graph-connectivity* 2)
|
|
|
|
(fill-outside-with-2 '(0 0 0) *day-18-test-graph-connectivity*)
|
|
;; this seems to work.
|
|
;; now i want to cound only outside that contacts 2?
|
|
;; so, same cound but look for neighbors 2 and count them, not 6 - stone-neighbors
|
|
|
|
(count-open-sides-to-outside *day-18-test-graph-connectivity*)
|
|
;; well, now i need to add 1 to all sides
|
|
|
|
(setq *day-18-test-input*
|
|
(coords-from-input "day18-test.txt"))
|
|
|
|
(setq *day-18-test-graph-connectivity*
|
|
(make-array (find-maxes *day-18-test-input*) :initial-element 0))
|
|
(fill-connectivity-array *day-18-test-input* *day-18-test-graph-connectivity*)
|
|
|
|
(fill-outside-with-2 '(0 0 0) *day-18-test-graph-connectivity*)
|
|
(count-open-sides-to-outside *day-18-test-graph-connectivity*)
|
|
;; and now it's 58
|
|
;; so, let's cound for full input?
|
|
|
|
;;; part 2
|
|
|
|
(setq *day-18-input-coords*
|
|
(coords-from-input "day18-input.txt"))
|
|
|
|
(setq *day-18-input-connectivity*
|
|
(make-array (find-maxes *day-18-input-coords*) :initial-element 0))
|
|
(fill-connectivity-array *day-18-input-coords* *day-18-input-connectivity*)
|
|
|
|
(fill-outside-with-2 '(0 0 0) *day-18-input-connectivity*)
|
|
(count-open-sides-to-outside *day-18-input-connectivity*)
|
|
;; 2484 - not correct, too low
|
|
;; there's 1 at the edge of the array. whoops. so there are 0s in the input?
|
|
;; yep. so now what, shift all by 1? and add one more +1 to the find max?
|
|
;; hahaha, this is stupid.
|
|
|
|
;; but let's do it
|
|
(coords-from-input "day18-test.txt") ; yep. +1
|
|
|
|
;; 2490
|