(defun input-lines (f) (with-open-file (s f) (loop for line = (read-line s nil 'eof) until (eq line 'eof) collect line))) (defun check-set (string red green blue) (multiple-value-bind (n begin) (parse-integer string :junk-allowed t) (cond ((search "red" string :start2 begin) (<= n red)) ((search "green" string :start2 begin) (<= n green)) ((search "blue" string :start2 begin) (<= n blue))))) (defun split-by-char (char string) (loop for i = 0 then (1+ j) as j = (position char string :start i) collect (subseq string i j) while j)) (defun check-round (string red green blue) (let ((sets (split-by-char #\, string))) (not (find-if-not (lambda (set) (check-set set red green blue)) sets)))) (defun check-game (string red green blue) (let ((pstring (nth 1 (split-by-char #\: string)))) (let ((rounds (split-by-char #\; pstring))) (not (find-if-not (lambda (set) (check-round set red green blue)) rounds))))) (defun solve1 (f) (loop for line in (input-lines f) as gid = (parse-integer line :junk-allowed t :start 5) when (check-game line 12 13 14) sum gid)) (defun cube-count (string color) (multiple-value-bind (n begin) (parse-integer string :junk-allowed t) (if (search color string :start2 begin) n 0))) (defun game-max-cubes (line color) (loop for i = (1+ (position #\: line)) then (1+ j) as j = (position-if (lambda (c) (or (equal c #\,) (equal c #\;))) line :start i) as count = (cube-count (subseq line i j) color) maximize count while j)) (defun solve2 (f) (loop for line in (input-lines f) as r = (game-max-cubes line "red") as g = (game-max-cubes line "green") as b = (game-max-cubes line "blue") sum (* r g b))) (print (solve1 "data/02/example.txt")) (print (solve1 "data/02/input.txt")) (print (solve2 "data/02/example.txt")) (print (solve2 "data/02/input.txt"))