advent-of-code-2023

My solutions to AoC 2023
git clone git://git.entf.net/advent-of-code-2023
Log | Files | Refs

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))))