96 lines
2.2 KiB
Rust
96 lines
2.2 KiB
Rust
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,
|
|
}
|
|
}
|
|
}
|