advent-of-code-2023

My solutions to AoC 2023
git clone git://git.entf.net/advent-of-code-2023
Log | Files | Refs

commit a94658845d70a2abb88f966d8378681a780ae91d
parent 3485ab4d7bc8df427f64ce0fdf79a9cdb55bccf5
Author: Lukas Henkel <lh@entf.net>
Date:   Mon, 11 Dec 2023 20:13:04 +0100

Day 10 task 2

Diffstat:
Msrc/day-10.lisp | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/utils.lisp | 9++++++++-
Mt/day-10.lisp | 53++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 116 insertions(+), 6 deletions(-)

diff --git a/src/day-10.lisp b/src/day-10.lisp @@ -53,18 +53,70 @@ when new-dir do (return (values dir new-point)))) +(defun find-position-pipe-type (pos started-at finished-at) + (let ((diff-s (point- started-at pos)) + (diff-e (point- finished-at pos))) + (or (switch (diff-s :test #'equal) + ((cons 1 0) + (switch (diff-e :test #'equal) + ((cons 0 1) #\F) + ((cons -1 0) #\-) + ((cons 0 -1) #\L))) + ((cons 0 1) + (switch (diff-e :test #'equal) + ((cons -1 0) #\7) + ((cons 0 -1) +char-pipe+))) + ((cons -1 0) + (when (equal diff-e (cons 0 -1)) #\J))) + (error "Invalid start and end nodes ~A / ~A" diff-s diff-e)))) + (defun task-1 (map dir pos) - (loop for steps from 1 + (loop with loop = (make-hash-table :test 'equal) + with coming-from = nil + for steps from 1 for pipe = (map-cell map pos) + do (setf (gethash pos loop) pipe) when (char= pipe #\S) - do (return (/ steps 2)) + do (return (values (/ steps 2) + loop + coming-from)) do (setf dir (walk dir pipe)) do (assert dir) - do (setf pos (point+ pos dir)))) + do (setf coming-from pos + pos (point+ pos dir)))) + +(defun crossing-pipe-p (pipe) + (cond + ((char= pipe +char-pipe+) t) + ((char= pipe #\L) #\7) + ((char= pipe #\F) #\J))) + +(defun task-2 (map loop) + (loop for y from 0 below (input-map-height map) + for in-loop? = nil + for crossing-when = nil + sum (loop for x from 0 below (input-map-width map) + for point = (cons x y) + for pipe = (map-cell map point) + for loop-pipe = (gethash point loop) + for crossing-pipe? = (and loop-pipe + (or (eql loop-pipe crossing-when) + (crossing-pipe-p loop-pipe))) + when (characterp crossing-pipe?) + do (setf crossing-when crossing-pipe? + crossing-pipe? nil) + when crossing-pipe? + do (setf in-loop? (not in-loop?)) + when (and in-loop? (not loop-pipe)) + sum 1))) (defun day-10 (input) (let* ((map (make-map input)) (start-pos (find-start-pos map))) (multiple-value-bind (dir pos) (find-first-step map start-pos) - (task-1 map dir pos)))) + (multiple-value-bind (task-1 loop coming-from) + (task-1 map dir pos) + (setf (gethash start-pos loop) + (find-position-pipe-type start-pos pos coming-from)) + (values task-1 (task-2 map loop)))))) diff --git a/src/utils.lisp b/src/utils.lisp @@ -13,6 +13,7 @@ #:map-cell #:map-integer-at #:point+ + #:point- #:point-x #:point-y #:point-neighbours @@ -101,7 +102,7 @@ :width width :height height)))) -(declaim (inline point+ point-x point-y) +(declaim (inline point+ point- point-x point-y) (ftype (function (cons) fixnum) point-x point-y)) (defun point-x (point) @@ -116,6 +117,12 @@ (the fixnum (+ (point-y point-a) (point-y point-b))))) +(defun point- (point-a point-b) + (cons (the fixnum (- (point-x point-a) + (point-x point-b))) + (the fixnum (- (point-y point-a) + (point-y point-b))))) + (declaim (inline map-cell map-integer-at) (ftype (function (input-map cons) character) map-cell)) diff --git a/t/day-10.lisp b/t/day-10.lisp @@ -17,4 +17,55 @@ SJ.L7 |F--J LJ...") - (assert= 8 task-1))) + (assert= 8 task-1)) + + (multiple-value-bind (task-1 task-2) + (aoc:run-day 10 "........... +.S-------7. +.|F-----7|. +.||.....||. +.||.....||. +.|L-7.F-J|. +.|..|.|..|. +.L--J.L--J. +...........") + (declare (ignore task-1)) + (assert= 4 task-2)) + (multiple-value-bind (task-1 task-2) + (aoc:run-day 10 ".......... +.S------7. +.|F----7|. +.||....||. +.||....||. +.|L-7F-J|. +.|..||..|. +.L--JL--J. +..........") + (declare (ignore task-1)) + (assert= 4 task-2)) + (multiple-value-bind (task-1 task-2) + (aoc:run-day 10 ".F----7F7F7F7F-7.... +.|F--7||||||||FJ.... +.||.FJ||||||||L7.... +FJL7L7LJLJ||LJ.L-7.. +L--J.L7...LJS7F-7L7. +....F-J..F7FJ|L7L7L7 +....L7.F7||L7|.L7L7| +.....|FJLJ|FJ|F7|.LJ +....FJL-7.||.||||... +....L---J.LJ.LJLJ...") + (declare (ignore task-1)) + (assert= 8 task-2)) + (multiple-value-bind (task-1 task-2) + (aoc:run-day 10 "FF7FSF7F7F7F7F7F---7 +L|LJ||||||||||||F--J +FL-7LJLJ||||||LJL-77 +F--JF--7||LJLJ7F7FJ- +L---JF-JLJ.||-FJLJJ7 +|F|F-JF---7F7-L7L|7| +|FFJF7L7F-JF7|JL---7 +7-L-JL7||F7|L7F-7F7| +L.L7LFJ|||||FJL7||LJ +L7JLJL-JLJLJL--JLJ.L") + (declare (ignore task-1)) + (assert= 10 task-2)))