Day 13
This commit is contained in:
parent
04f4adc410
commit
a91b120155
5 changed files with 255 additions and 1 deletions
95
src/day13.rs
Normal file
95
src/day13.rs
Normal 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
11
src/grammars/day13.pest
Normal 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 }
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
Reference in a new issue