day-2.lisp (1937B)
1 (defpackage #:aoc/day-2 2 (:use #:cl #:aoc/utils) 3 (:export #:day-2)) 4 (in-package #:aoc/day-2) 5 6 (declaim (ftype (function (simple-string fixnum) list) parse-sets)) 7 (defun parse-sets (line start) 8 (loop with sets = nil 9 with red = 0 10 with green = 0 11 with blue = 0 12 with length = (length line) 13 for pos from start 14 do (multiple-value-bind (n end) 15 (parse-integer line :start pos :junk-allowed t) 16 (setf pos end) 17 (ecase (aref line (1+ pos)) 18 (#\r (setf red n 19 pos (+ pos 4))) 20 (#\g (setf green n 21 pos (+ pos 6))) 22 (#\b (setf blue n 23 pos (+ pos 5))))) 24 while (< pos length) 25 when (char= (aref line pos) #\;) 26 do (push (list red green blue) sets) 27 and do (setf red 0 green 0 blue 0) 28 finally (return (cons (list red green blue) sets)))) 29 30 (declaim (ftype (function (simple-string) list) parse-game-line)) 31 (defun parse-game-line (line) 32 (multiple-value-bind (game-id colon-pos) 33 (parse-integer line :start 5 :junk-allowed t) 34 (list game-id 35 (parse-sets line (1+ colon-pos))))) 36 37 (defparameter *minimum-cubes* (list 12 13 14)) 38 39 (defun game-possible-p (sets) 40 (loop for set in sets 41 always (loop for color-1 fixnum in set 42 for color-2 fixnum in *minimum-cubes* 43 always (<= color-1 color-2)))) 44 45 (declaim (ftype (function (list) fixnum) game-power)) 46 (defun game-power (sets) 47 (apply #'* (apply (curry #'mapcar #'max) sets))) 48 49 (defun day-2 (input) 50 (loop for line = (read-line input nil) 51 while line 52 for (game sets) (fixnum list) = (parse-game-line line) 53 when (game-possible-p sets) 54 sum game into task-1 fixnum 55 sum (game-power sets) into task-2 fixnum 56 finally (return (values task-1 task-2))))