diff options
Diffstat (limited to 'AoC2023')
-rw-r--r-- | AoC2023/day02/solver.lisp | 60 |
1 files changed, 28 insertions, 32 deletions
diff --git a/AoC2023/day02/solver.lisp b/AoC2023/day02/solver.lisp index 60aa3cf..c0c0d70 100644 --- a/AoC2023/day02/solver.lisp +++ b/AoC2023/day02/solver.lisp @@ -1,10 +1,14 @@ (ql:quickload '(uiop fiveam cl-ppcre)) + (defparameter eg-input "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green") +(defstruct bag + (red 0) (blue 0) (green 0)) + (defun parse-set (info) (let (list) (cl-ppcre:do-register-groups ((#'parse-integer count) (#'read-from-string color)) @@ -12,28 +16,36 @@ Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green") (push (list color count) list)) list)) -(defun in-limits (max-red max-green max-blue) - (lambda (value) - (destructuring-bind (color count) value - (<= count - (ecase color - (red max-red) - (green max-green) - (blue max-blue)))))) +(defun in-limits (bag) + (lambda (sample) + (every (lambda (value) + (destructuring-bind (color count) value + (<= count (slot-value bag color)))) + (parse-set sample)))) (defun parse-game (game-bounds) (lambda (line) (destructuring-bind (game . sets) (uiop:split-string line :separator '(#\; #\:)) - (if (every - (lambda (s) - (every game-bounds (parse-set s))) - sets) + (if (every game-bounds sets) (parse-integer (cl-ppcre:scan-to-strings "\\d+" game)) 0)))) +(defun bag-power (bag) + (with-slots (red blue green) bag + (* red blue green))) + +(defun max-set (top set) + (loop for (color count) in set do + (setf (slot-value top color) + (max (slot-value top color) count))) + top) + (defun game-powers (line) - (apply #'* (mapcar #'cadr (parse-set (cdr (uiop:split-string line :separator '(#\; #\:))))))) + (bag-power + (reduce #'max-set (cdr (uiop:split-string line :separator '(#\; #\:))) + :key #'parse-set + :initial-value (make-bag)))) (defun solve1 (lines bounds) (reduce @@ -41,36 +53,20 @@ Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green") lines :key (parse-game bounds))) - -(defun max-set (top set) - (loop for (color count) in set do - (let ((var (ecase color - (red 0) - (green 1) - (blue 2)))) - (setf (elt top var) (max (elt top var) count)))) - top) - (defun solve2 (lines) - (apply #'+ - (mapcar (lambda (line) - (apply #'* - (reduce #'max-set (cdr (uiop:split-string line :separator '(#\; #\:))) - :key #'parse-set - :initial-value (make-list 3 :initial-element 0)))) - lines))) + (reduce #'+ lines :key #'game-powers)) (fiveam:test solutions (fiveam:is (= 8 (solve1 (uiop:split-string eg-input :separator '(#\Newline)) - (in-limits 12 13 14)))) + (in-limits (make-bag :red 12 :green 13 :blue 14 ))))) (fiveam:is (= 2369 (solve1 (uiop:read-file-lines "input") - (in-limits 12 13 14)))) + (in-limits (make-bag :red 12 :green 13 :blue 14 ))))) (fiveam:is (= 2286 (solve2 (uiop:split-string eg-input :separator '(#\Newline))))) |