;; https://adventofcode.com/2022/day/22 (in-package :day-22) ;; monkey map. so, i'd want to store the map. ;; and have functions that return "neighbors" maybe as alist? ;; neighbor is the right place to calculate wrapping around empty space ;; on top of neighbors get walkable directions ;; how to best represent coord? ;; next - moving ;; looking at the map of input. maybe somehow precompute where to jump on the map? ;; nah. ;; so, let's get map. with chars space, dot, hash ;; have line of spaces at the start, end, left and right? ;; that would shift coords by +1 ;; and i'd also like what? i'd also like to store the path? ;; when exiting save that last orientation at the point? ;; and only treat space and hast as special, dot and arrows as walkable ;; or i could print "every snapshot" with setting and removing the walkout ;; i could split the input into files, that would simplify things ;; let's read the map into array? (setq *ugh* (let* ((lines (uiop:read-file-lines "day22-test-map.txt")) (rows (length lines)) (cols (apply #'max (mapcar #'length lines))) (arr (make-array (list (+ 2 rows) (+ 2 cols)) ; adding for padding row of empty space :initial-element #\ ))) (loop for row from 0 below rows for line = (coerce (nth row lines) 'array) do (loop for col from 0 below cols for char = (if (array-in-bounds-p line col) (aref line col) #\ ) do (setf (aref arr (1+ row) (1+ col)) char))) arr)) (setq *test-arr-out-bounds* (make-array '(2 2) :initial-element #\. :adjustable t)) (print-map *ugh*) ;; yep, this is what i want (print-map (read-map-to-array "day22-map.txt")) (setq *ugh* (read-map-to-array "day22-test-map.txt")) ;; seems to work. ;; what are next steps? ;; ;; for some coords get neighboring to four sides ;; this should just return coords even with wrapping ;; let's first do function that returns coord or wrapped coord if value is space? (alexandria:assoc-value *movements* 'left) ;; so from coord as list to updated coord (move-coord-one-step '(1 1) 'right) ;; next should check the value of the moved. and if it's space - ;; calculate wrap ;; would also take the map array ;; if we're out of bounds, just skip this movement. shouldn't happen in my data (opposite-movement 'left) (opposite-movement 'right) (opposite-movement 'down) (opposite-movement 'up) (apply #'aref *ugh* '(1 12)) ;; now i need to check that. hm. *ugh* (print-map *ugh*) '(4 1) ; begining of part (move-with-possible-wrap '(5 1) 'left *ugh*) (aref *ugh* 5 0) (let ((coord '(5 1)) (map *ugh*) (direction 'left)) (do ((mov-coord coord (move-coord-one-step mov-coord (opposite-movement direction)))) ((equal #\ (apply #'aref map mov-coord)) (move-coord-one-step mov-coord direction)))) ;; now? um (move-with-possible-wrap '(5 2) 'up *ugh*) ; now that seems ok ;; next is from 'move-with-possible-wrap ;; i guess i'd alreay want to display? ;; set X on that coord? (display-coord '(5 2) *ugh*) (display-coord (move-with-possible-wrap '(5 2) 'up *ugh*) *ugh*) ;; yeah, kind of ok. ;; what next? simulate movement? (move 4 'right '(1 1) *ugh*) (display-coord '(6 1) *ugh*) (display-coord (move 4 'right '(6 1) *ugh*) *ugh*) (display-coord '(6 8) *ugh*) (display-coord (move-with-possible-wrap '(6 8) 'left *ugh*) *ugh*) (display-coord (move 1 'left '(6 8) *ugh*) *ugh*) (display-coord (move 2 'left '(6 8) *ugh*) *ugh*) (display-coord (move 3 'left '(6 8) *ugh*) *ugh*) (display-coord '(6 8) *ugh*) (display-coord (move-with-possible-wrap '(6 8) 'right *ugh*) *ugh*) (display-coord (move 1 'right '(6 8) *ugh*) *ugh*) (display-coord (move 2 'right '(6 8) *ugh*) *ugh*) (display-coord (move 3 'right '(6 8) *ugh*) *ugh*) (display-coord '(6 2) *ugh*) (display-coord (move-with-possible-wrap '(6 2) 'left *ugh*) *ugh*) (display-coord (move 1 'left '(6 2) *ugh*) *ugh*) (display-coord (move 2 'left '(6 2) *ugh*) *ugh*) (display-coord (move 3 'left '(6 2) *ugh*) *ugh*) (display-coord (move 4 'left '(6 2) *ugh*) *ugh*) (display-coord (move 5 'left '(6 2) *ugh*) *ugh*) (display-coord (move 6 'left '(6 2) *ugh*) *ugh*) ;; ok, i guess ;; ;; and now code the walk? (defparameter *test-path* "10R5L5R10L4R5L5") (ppcre:split "(L|R|U|D])" *test-path* :with-registers-p t ) ;; somewhat of what i want, but also lrud into words (mapcar #'parse-integer-or-symbol (ppcre:split "(L|R)" *test-path* :with-registers-p t )) ;; initial number is "forward" from initial direction ;; oh, so the path is with turns Right turn or Left turn. ;; with initial Right ;; so, now i'd want a fuction that transformes direction ;; i guess i could what? make cyclic list? not quite i guess (alexandria:circular-list 'up 'right 'down 'left) (position 'up (alexandria:circular-list 'up 'right 'down 'left)) (nth (mod -1 4) (alexandria:circular-list 'up 'right 'down 'left)) ;; yeah i guess (new-direction 'UP 'L) (new-direction 'LEFT 'L) (new-direction 'down 'L) (new-direction 'right 'L) (new-direction 'UP 'R) (new-direction 'LEFT 'R) (new-direction 'down 'R) (new-direction 'right 'R) ;; yay. that's kind of ok ;; now. ugh ;; yup, let's add that in code... (append (read-path "day22-test-path.txt") (list 'L)) (read-path "day22-path.txt") ;; the path is "go N to your direction" ;; then L or R to change direction ;; so, now the main loop? ;; i guess i could add one more R or L to the end ;; and treat path as (n turn-direction) ;; oh, but the final direction is part of the answer ;; OK, LET'S add L to the end (let ((padded-path (append (read-path "day22-test-path.txt") (list 'L))) (direction 'right) (coords '(1 1)) ; to be calculated (map *ugh*) ) (loop for (n turn-direction) on padded-path by #'cddr do (progn (setq coords (move n direction coords map)) (setq direction (new-direction direction turn-direction))) finally (return (list coords direction)))) ;; hoho. the task requires indices starting from 1, cool ;; and i did 1 too many left turns, so let's turn right ;; UP to right, is RIGHT ;; and 0 for right, cool ;; yay! now let's clean it up. ;; one more thing. determining top leftmost point. (get-topmost-left-coords *ugh*) (print-map *ugh*) (apply #'calc-password (walk-path "day22-test-path.txt" "day22-test-map.txt")) (apply #'calc-password (walk-path "day22-path.txt" "day22-map.txt")) ;; 11464 ;; and one gold star. ;;; and PART 2. ;; then neighbors is different ;; especially the wrap thing. ;; how'd i calc that? for the map? ugh ;; so, it's 6 parts. huh. ugh ;; oh, they're oblong, but they are all 4 by 4 ;; XX ;; X ;; XX ;; X ;; outline of my input ;; how do i get freaking folding? ;; ugh. ;; maybe go for the next? um. ;; yeah. i'm giving up for now. let's go to rest for the new years. 19:33 of Dec 31st ;; fare well Common Lisp, I'll return to use in Q2 or Q3