(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") (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 (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 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) (parse-integer (cl-ppcre:scan-to-strings "\\d+" game)) 0)))) (defun game-powers (line) (apply #'* (mapcar #'cadr (parse-set (cdr (uiop:split-string line :separator '(#\; #\:))))))) (defun solve1 (lines bounds) (reduce #'+ 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))) (fiveam:test solutions (fiveam:is (= 8 (solve1 (uiop:split-string eg-input :separator '(#\Newline)) (in-limits 12 13 14)))) (fiveam:is (= 2369 (solve1 (uiop:read-file-lines "input") (in-limits 12 13 14)))) (fiveam:is (= 2286 (solve2 (uiop:split-string eg-input :separator '(#\Newline))))) (fiveam:is (= 66363 (solve2 (uiop:read-file-lines "input")))))