USING: accessors combinators formatting io.directories io.encodings.utf8 io.files io.pathnames kernel literals math math.parser namespaces regexp sequences source-files splitting tools.time ; IN: aoc2023.day2 TUPLE: game { num integer } { sets sequence } ; : ( -- game ) game new ; TUPLE: game-set { red integer initial: 0 } { green integer initial: 0 } { blue integer initial: 0 } ; : ( -- game-set ) game-set new ; : parse-game-set ( string -- game-set ) "," split [ R/ \d+|red|green|blue/ all-matching-subseqs ] map [ [ first dec> ] [ second ] bi { { "red" [ >>red ] } { "green" [ >>green ] } { "blue" [ >>blue ] } } case ] reduce ; : parse-game ( seq -- game ) swap [ first 5 cut nip dec> >>num ] ! set game number [ rest [ parse-game-set ] map >>sets ] bi ; : day2-part1 ( seq -- sum ) [ sets>> [ [ red>> 12 <= ] [ green>> 13 <= ] [ blue>> 14 <= ] tri and and ] all? ] filter [ num>> ] map sum ; : day2-part2 ( seq -- sum ) [ sets>> [ [ red>> ] map supremum ] [ [ green>> ] map supremum ] [ [ blue>> ] map supremum ] tri * * ] map sum ; : ns2ms ( i -- f ) 1000 /i 1000 /f ; : day2-main ( -- ) $[ current-source-file get path>> parent-directory ] [ "input.txt" utf8 file-contents ] with-directory split-lines [ ":;" split ] map [ parse-game ] map [ [ day2-part1 ] benchmark ns2ms "part1. answer: %5d, time: %.3f ms.\n" printf ] [ [ day2-part2 ] benchmark ns2ms "part2. answer: %5d, time: %.3f ms.\n" printf ] bi ; MAIN: day2-main