Created
December 13, 2024 17:49
-
-
Save qookei/e698a8c32af61166dde82142d6357ca3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(use-modules (srfi srfi-1) | |
(ice-9 match) (ice-9 peg) | |
(ice-9 textual-ports) | |
(ice-9 pretty-print)) | |
(define-peg-string-patterns | |
"top <-- (entry NL?)* !. | |
entry <-- button NL button NL prize NL | |
prize <-- PRIZE vec | |
button <-- BUTTON ('A'/'B') COLON vec | |
vec <-- X number COMMA Y number | |
number <-- [0-9]+ | |
X < 'X' ('+'/'=') | |
Y < 'Y' ('+'/'=') | |
BUTTON < 'Button ' | |
PRIZE < 'Prize: ' | |
COLON < ': ' | |
COMMA < ', ' | |
NL < '\n' | |
") | |
(define (parse-number num) | |
(string->number (second num))) | |
(define (parse-vec vec) | |
(cons (parse-number (second vec)) | |
(parse-number (third vec)))) | |
(define (parse-button btn) | |
(parse-vec (third btn))) | |
(define (parse-prize prize) | |
(parse-vec (second prize))) | |
(define (parse-entry entry) | |
(list (parse-button (second entry)) | |
(parse-button (third entry)) | |
(parse-prize (fourth entry)))) | |
;; / | |
;; | a*Xa + b*Xb = Xp | |
;; | a*Ya + b*Yb = Yp | |
;; \ | |
;; / | |
;; | a + b*Xb/Xa = Xp/Xa | |
;; | a + b*Yb/Ya = Yp/Ya | |
;; \ | |
;; ---------------------- | |
;; b*Xb/Xa - b*Yb/Ya = Xp/Xa - Yp/Ya | |
;; b*(Xb/Xa - Yb/Ya) = Xp/Xa - Yp/Ya | |
;; b = (Xp/Xa - Yp/Ya) / (Xb/Xa - Yb/Ya) | |
;; => | |
;; a + b*Xb/Xa = Xp/Xa | |
;; a = Xp/Xa - b*Xb/Xa | |
;; a = (Xp - b*Xb)/Xa | |
;; Valid solution only if a,b in N_+ | |
(define (win-cost entry) | |
(match-let* ([(a-button b-button prize) entry] | |
[b (/ (- (/ (car prize) (car a-button)) | |
(/ (cdr prize) (cdr a-button))) | |
(- (/ (car b-button) (car a-button)) | |
(/ (cdr b-button) (cdr a-button))))] | |
[a (/ (- (car prize) | |
(* b (car b-button))) | |
(car a-button))] | |
[cost (+ (* 3 a) b)]) | |
(if (and (integer? a) | |
(integer? b)) | |
cost | |
0))) | |
(define (part2-entry entry) | |
(list (first entry) | |
(second entry) | |
(cons (+ 10000000000000 | |
(car (third entry))) | |
(+ 10000000000000 | |
(cdr (third entry)))))) | |
(let* ([input (get-string-all (current-input-port))] | |
[peg-tree (peg:tree (match-pattern top input))] | |
[entries (map parse-entry (cdr peg-tree))]) | |
(pretty-print (fold + 0 (map win-cost entries))) | |
(pretty-print (fold + 0 (map (compose win-cost part2-entry) entries)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment