aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2023/day10
diff options
context:
space:
mode:
Diffstat (limited to 'AoC2023/day10')
-rw-r--r--AoC2023/day10/solver.lisp86
1 files 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")))))