From 4ced0399644ff2b75b53ce26d6afb0688e78b264 Mon Sep 17 00:00:00 2001 From: Oscar Najera Date: Thu, 14 Dec 2023 09:11:34 +0100 Subject: solve part2 --- AoC2023/day10/solver.lisp | 86 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 19 deletions(-) diff --git a/AoC2023/day10/solver.lisp b/AoC2023/day10/solver.lisp index fcc1eed..d93617a 100644 --- a/AoC2023/day10/solver.lisp +++ b/AoC2023/day10/solver.lisp @@ -3,10 +3,10 @@ (ql:quickload '(fiveam)) (defparameter directions - '((up 0 -1) - (dw 0 1) - (lf -1 0) - (rt 1 0))) + '((up -1 0) + (dw 1 0) + (lf 0 -1) + (rt 0 1))) (defparameter pipes '((#\| up dw) @@ -32,7 +32,7 @@ LJ.LJ") (cdr (assoc point pipes)))) (fiveam:test parts - (fiveam:is (equal '((-1 0) (1 0)) + (fiveam:is (equal '((0 -1) (0 1)) (get-neighbors #\-)))) @@ -52,7 +52,7 @@ LJ.LJ") (< -1 x xmax)) (list y x))))) (destructuring-bind (y x) point - (loop for (dx dy) in (get-neighbors (aref (aref map y) x)) + (loop for (dy dx) in (get-neighbors (aref (aref map y) x)) when (bounds (+ y dy) (+ x dx)) collect it)))) (defun start-neighbors (map start) @@ -67,21 +67,69 @@ LJ.LJ") (cadr next) (car next)))) -(defun solver1 (rows) - (let* ((map (make-array (length rows) :initial-contents rows)) - (start (find-start map)) +(defun get-loop (map) + (let* ((start (find-start map)) (options (start-neighbors map start)) (last start) - (cur (car options)) - ) - (loop - for next = (advance-next map cur last) - for steps from 1 - until (equal next start) - do (setf last cur - cur next) - finally (return (floor (+ steps 1) 2))))) + (cur (car options))) + (cons cur + (loop + for next = (advance-next map cur last) + do (setf last cur + cur next) + collect next + until (equal next start))))) +;; (get-loop +;; (uiop:split-string eg-input :separator '(#\Newline))) + +(defun solver1 (rows) + (let ((map (make-array (length rows) :initial-contents rows))) + (floor (length (get-loop map)) 2))) + +;; To know if a point is inside a loop, I need to count how often a ray crosses +;; until it reaches the boundary. I can just count to the right. +;; In this case only the vertical edges count, and element that change direction. +;; Meaning LJ is a u, same as F7 an n, that means the ray passes tangent across +;; those 2 cells taking the point a bit lower, would mean only counting pipes +;; with down component thus F,|,7. The rest L,-,J are irrelevant. + +(defun in-loop-p (point loop) + (member point loop :test #'equal)) + +(defun rassoc-get (item list) + (car (rassoc item list :test #'equal))) + +(defun correct-start (map) + (let ((start (find-start map))) + (setf (aref (aref map (car start)) (cadr start)) + (rassoc-get + (loop for (y x) in (start-neighbors map start) + collect + (rassoc-get (list (- y (first start)) + (- x (second start))) + directions)) + pipes)))) + +(defun solver2 (rows) + (let* ((map (make-array (length rows) :initial-contents rows)) + (loop-tiles (get-loop map)) + insidep) + (correct-start map) + (loop for row across map + for y from 0 do + (setf insidep nil) + sum + (loop for col across row + for x from 0 + for point = (list y x) + when (and (in-loop-p point loop-tiles) + (member col '(#\F #\| #\7))) + do (setf insidep (not insidep)) + count (and (not (in-loop-p point loop-tiles)) + insidep))))) (fiveam:test solution (fiveam:is (= 8 (solver1 (uiop:split-string eg-input :separator '(#\Newline))))) - (fiveam:is (= 6812 (solver1 (uiop:read-file-lines "input"))))) + (fiveam:is (= 6812 (solver1 (uiop:read-file-lines "input")))) + (fiveam:is (= 1 (solver2 (uiop:split-string eg-input :separator '(#\Newline))))) + (fiveam:is (= 527 (solver2 (uiop:read-file-lines "input"))))) -- cgit v1.2.3