advent-of-code-2024

My solutions to AoC 2024
Log | Files | Refs

day-13.lisp (2160B)


      1 (defpackage #:aoc/day-13
      2   (:use #:cl #:aoc/utils)
      3   (:export #:day-13))
      4 (in-package #:aoc/day-13)
      5 
      6 (defstruct claw-machine
      7   (button-a)
      8   (button-b)
      9   (prize))
     10 
     11 (defun parse-coord-line (line)
     12   (let* ((offset (if (char= (aref line 0) #\P) 1 0))
     13          (colon (position #\: line))
     14          (pair (uiop:split-string (subseq line (+ colon 2)) :separator '(#\,)))
     15          (x (first pair))
     16          (y (second pair))
     17          (x (parse-integer x :start (1+ offset)))
     18          (y (parse-integer y :start (+ 2 offset))))
     19     (cons x y)))
     20 
     21 (defun parse-claw-machine (input)
     22   (let ((l-1 (read-line input nil))
     23         (l-2 (read-line input nil))
     24         (l-3 (read-line input nil)))
     25     (read-line input nil)
     26     (when (or (null l-1) (null l-2) (null l-3))
     27       (return-from parse-claw-machine nil))
     28     (make-claw-machine :button-a (parse-coord-line l-1)
     29                        :button-b (parse-coord-line l-2)
     30                        :prize (parse-coord-line l-3))))
     31 
     32 (defun parse-claw-machines (input)
     33   (loop for machine = (parse-claw-machine input)
     34         until (null machine)
     35         collect machine))
     36 
     37 (defun play (machine prize-x prize-y)
     38   (let* ((button-a (claw-machine-button-a machine))
     39          (button-b (claw-machine-button-b machine))
     40          (xb (* (point-x button-b) (point-y button-a)))
     41          (yb (* (point-y button-b) (point-x button-a)))
     42          (px (* prize-x (point-y button-a)))
     43          (py (* prize-y (point-x button-a)))
     44          (b (/ (- py px) (- yb xb)))
     45          (a (/ (- prize-x (* (point-x button-b) b))
     46                (point-x button-a))))
     47     (when (and (integerp a)
     48                (integerp b))
     49       (+ (* a 3) b))))
     50 
     51 (defun day-13 (input)
     52   (loop with machines = (parse-claw-machines input)
     53         for machine in machines
     54         for prize = (claw-machine-prize machine)
     55         for prize-x = (point-x prize)
     56         for prize-y = (point-y prize)
     57         sum (or (play machine prize-x prize-y) 0) into task-1
     58         sum (or (play machine
     59                       (+ prize-x 10000000000000)
     60                       (+ prize-y 10000000000000))
     61                 0) into task-2
     62         finally (return (values task-1 task-2))))