(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)) ("(\\d+) (blue|red|green)" info) (push (list color count) list)) list)) (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 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) (bag-power (reduce #'max-set (cdr (uiop:split-string line :separator '(#\; #\:))) :key #'parse-set :initial-value (make-bag)))) (defun solve1 (lines bounds) (reduce #'+ lines :key (parse-game bounds))) (defun solve2 (lines) (reduce #'+ lines :key #'game-powers)) (fiveam:test solutions (fiveam:is (= 8 (solve1 (uiop:split-string eg-input :separator '(#\Newline)) (in-limits (make-bag :red 12 :green 13 :blue 14 ))))) (fiveam:is (= 2369 (solve1 (uiop:read-file-lines "input") (in-limits (make-bag :red 12 :green 13 :blue 14 ))))) (fiveam:is (= 2286 (solve2 (uiop:split-string eg-input :separator '(#\Newline))))) (fiveam:is (= 66363 (solve2 (uiop:read-file-lines "input")))))