Last active
December 2, 2023 10:21
-
-
Save qookei/5ef743e9920cbc7d8732d64c6e3c8ceb 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 textual-ports) (ice-9 peg) | |
(ice-9 pretty-print) (ice-9 format) (ice-9 match)) | |
;; Parsing | |
(define-peg-string-patterns | |
"game <-- GAME number COLON (round SEMI)* round NL | |
round <-- (ball COMMA)* ball | |
ball <-- number SPC color | |
color <-- [a-z]+ | |
number <- [0-9]+ | |
COMMA < ', ' | |
SEMI < '; ' | |
COLON < ': ' | |
GAME < 'Game ' | |
SPC < ' ' | |
NL < '\n'") | |
(define-peg-pattern games all (peg "game* !.")) | |
(define (process-round round-tree) | |
(map (λ (ball) | |
(cons (second (third ball)) | |
(string->number (second ball)))) | |
(keyword-flatten '(ball color) (cdr round-tree)))) | |
(define (process-game game-tree) | |
(cons (string->number (second game-tree)) | |
(map process-round (cddr (keyword-flatten '(round) game-tree))))) | |
(define (process-games games-tree) | |
(map process-game (cdr games-tree))) | |
;; Part 1 | |
(define (round-possible? round-alist) | |
(every (λ (max) | |
(match (assoc (car max) round-alist) | |
[(k . v) (<= v (cdr max))] | |
[_ #t])) | |
'(("red" . 12) | |
("green" . 13) | |
("blue" . 14)))) | |
(define (game-possible? game-cons) | |
(every round-possible? (cdr game-cons))) | |
(define (part1 games-alist) | |
(fold + 0 (map car (filter game-possible? games-alist)))) | |
;; Part 2 | |
(define (max-balls alist-1 alist-2) | |
(map (λ (cons-2) | |
(match (assoc (car cons-2) alist-1) | |
[(k . v) (cons (car cons-2) (max (cdr cons-2) v))] | |
[_ cons-2])) | |
alist-2)) | |
(define (set-power game-cons) | |
(fold * 1 | |
(map cdr (fold max-balls | |
'(("red" . 0) ("green" . 0) ("blue" . 0)) | |
(cdr game-cons))))) | |
(define (part2 games-alist) | |
(fold + 0 (map set-power games-alist))) | |
(let* ([input (get-string-all (current-input-port))] | |
[tree (peg:tree (match-pattern games input))] | |
[games-alist (process-games tree)]) | |
(format #t "Part 1: ~a~%" (part1 games-alist)) | |
(format #t "Part 2: ~a~%" (part2 games-alist))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment