This commit is contained in:
sepia 2024-12-13 14:50:19 -06:00
parent 04f4adc410
commit a91b120155
5 changed files with 255 additions and 1 deletions

95
src/day13.rs Normal file
View file

@ -0,0 +1,95 @@
use itertools::Itertools;
use pest::{
iterators::{Pair, Pairs},
Parser,
};
const OFFSETS: (u64, u64) = (10000000000000, 10000000000000);
pub fn day13() {
let cost: f64 = parse_machines(&crate::input(13))
.iter()
.filter_map(|machine| {
let (c, d) = machine.prize;
let (a, b) = &machine.buttons;
let bn = (d - c * a.y / a.x) / (b.y - b.x * a.y / a.x);
let an = (c - bn * b.x) / a.x;
// Both solutions must be whole numbers
let winnable = [an, bn]
.iter()
.all(|&n| n >= -0.01 && (n.round() - n).abs() <= 0.01);
if winnable {
Some(an.round() * a.cost + bn.round() * b.cost)
} else {
None
}
})
.sum();
println!("Minimum Cost: {:?}", cost);
}
struct Machine {
buttons: (Button, Button),
prize: (f64, f64),
}
struct Button {
cost: f64,
x: f64,
y: f64,
}
#[derive(pest_derive::Parser)]
#[grammar = "grammars/day13.pest"]
struct MachinesParser {}
fn parse_machines(input: &str) -> Vec<Machine> {
MachinesParser::parse(Rule::machines, input)
.unwrap()
.nth(0)
.unwrap()
.into_inner()
.map(Pair::<'_, Rule>::into_inner)
.map(Machine::parse)
.collect()
}
impl Machine {
fn parse(input: Pairs<'_, Rule>) -> Self {
let (a, b, prize) = input.map(|p| p.into_inner()).collect_tuple().unwrap();
let buttons = [a, b]
.into_iter()
.map(Button::parse)
.collect_tuple()
.unwrap();
let prize = prize
.map(|n| n.as_str().parse::<u64>().unwrap())
.collect_tuple()
.map(|(x, y)| ((x + OFFSETS.0) as f64, (y + OFFSETS.1) as f64))
.unwrap();
Self { buttons, prize }
}
}
impl Button {
fn parse(input: Pairs<'_, Rule>) -> Self {
let (t, x, y) = input.collect_tuple().unwrap();
let cost = match t.as_str() {
"A" => 3.,
"B" => 1.,
_ => unreachable!(),
};
Self {
x: x.as_str().parse::<f64>().unwrap(),
y: y.as_str().parse::<f64>().unwrap(),
cost,
}
}
}

11
src/grammars/day13.pest Normal file
View file

@ -0,0 +1,11 @@
_WHITESPACE = _{ " " }
newline = _{ "\n" }
number = { ASCII_DIGIT+ }
button_type = { "A" | "B" }
button = { "Button " ~ button_type ~ ": X+" ~ number ~ ", Y+" ~ number ~ newline }
prize = { "Prize: X=" ~ number ~ ", Y=" ~ number ~ newline }
machine = { button ~ button ~ prize ~ newline? }
eoi = _{ !ANY }
machines = { SOI ~ machine+ ~ eoi }

View file

@ -22,10 +22,12 @@ mod day9;
mod day10;
#[allow(dead_code)]
mod day11;
#[allow(dead_code)]
mod day12;
mod day13;
fn main() {
day12::day12();
day13::day13();
}
pub fn input(day: u8) -> String {