advent-23/p02.janet
2023-12-04 23:59:49 -05:00

96 lines
2.4 KiB
Plaintext
Executable file

#!/usr/bin/env janet
(use spork/test)
(def peg
'{:color
(+
(/ "red" :red)
(/ "green" :green)
(/ "blue" :blue))
:game-num (* "Game " (number :d+) ": ")
:color-group (group (* (number :d+) " " :color))
:subset (group (* (any (* :color-group ", ")) :color-group))
:main (* :game-num (group (* (any (* :subset "; ")) :subset)))})
(defn pmatch [input] (peg/match peg input))
(defn subset-pred
"Check a predicate against a subset"
[subset pred]
(all (fn [pair] (pred pair)) subset))
(defn all-pred
"Check if all subsets satisfy a predicate"
[subsets pred]
(all (fn [subset] (subset-pred subset pred)) subsets))
(def *die-pool*
@{:red 12
:green 13
:blue 14})
(defn possible
"Check if die fits in the die pool"
[pair]
(var [count color] pair)
(<= count (*die-pool* color)))
(defn create-pool [init]
@{:red init
:green init
:blue init})
(defn create-pool-walker
"Build up the die pool"
[pool]
(fn [pair]
(var [count color] pair)
(set (pool color) (max (pool color) count))))
(defn all-possible
"Check if all fit the pool"
[subsets]
(all-pred subsets possible))
(defn solve [lines]
(defn calc-power [pool]
(* (splice (values pool))))
(var power-sum 0)
(each line lines
(var pool (create-pool 0))
(var [game subsets] (pmatch line))
(all-pred subsets (create-pool-walker pool))
(pp pool)
(+= power-sum (calc-power pool)))
(print power-sum))
(start-suite)
(def example
["Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green"
"Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue"
"Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red"
"Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red"
"Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"])
(assert (deep= @[42
@[@[@[1 :blue] @[4 :red]]
@[@[3 :green]]]]
(pmatch "Game 42: 1 blue, 4 red; 3 green")))
(assert (possible @[12 :blue]))
(assert (not (possible @[25 :blue])))
(def impossible-match
(pmatch "Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red"))
(def possible-match
(pmatch "Game 3: 8 green, 6 blue, 10 red; 5 blue, 4 red, 13 green; 5 green, 1 red"))
(assert (not (all-possible (impossible-match 1))))
(assert (all-possible (possible-match 1)))
(end-suite)
(print (with [f (file/open "p02.txt")] (solve (file/lines f))))