Dag 13 af, was makkelijk als je het gewoon direct uitrekende
This commit is contained in:
7
advent_of_code/2024/13/Cargo.toml
Normal file
7
advent_of_code/2024/13/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "main"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
nom = "7.1.3"
|
||||||
1279
advent_of_code/2024/13/input.txt
Normal file
1279
advent_of_code/2024/13/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
163
advent_of_code/2024/13/src/main.rs
Normal file
163
advent_of_code/2024/13/src/main.rs
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
use nom::{
|
||||||
|
bytes::complete::tag,
|
||||||
|
character::complete::{i64, multispace1},
|
||||||
|
multi::many1,
|
||||||
|
sequence::{delimited, separated_pair, tuple},
|
||||||
|
IResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn parse(input: &str) -> IResult<&str, Vec<((i64, i64), (i64, i64), (i64, i64))>> {
|
||||||
|
let (_input, result) = many1(tuple((
|
||||||
|
delimited(
|
||||||
|
tag("Button A: X+"),
|
||||||
|
separated_pair(i64, tag(", Y+"), i64),
|
||||||
|
multispace1,
|
||||||
|
),
|
||||||
|
delimited(
|
||||||
|
tag("Button B: X+"),
|
||||||
|
separated_pair(i64, tag(", Y+"), i64),
|
||||||
|
multispace1,
|
||||||
|
),
|
||||||
|
delimited(
|
||||||
|
tag("Prize: X="),
|
||||||
|
separated_pair(i64, tag(", Y="), i64),
|
||||||
|
multispace1,
|
||||||
|
),
|
||||||
|
)))(input)?;
|
||||||
|
|
||||||
|
Ok((input, result))
|
||||||
|
}
|
||||||
|
|
||||||
|
// For a / b
|
||||||
|
fn divisible(a: f64, b: f64, epsilon: f64) -> bool {
|
||||||
|
let div = a / b;
|
||||||
|
|
||||||
|
(div - div.round()).abs() < epsilon
|
||||||
|
}
|
||||||
|
|
||||||
|
fn equal(a: f64, b: f64, epsilon: f64) -> bool {
|
||||||
|
(a - b).abs() < epsilon
|
||||||
|
}
|
||||||
|
|
||||||
|
fn linear_solve_1(a: (i64, i64), b: (i64, i64), prize: (i64, i64)) -> Option<i64> {
|
||||||
|
const EPS: f64 = 0.000001;
|
||||||
|
|
||||||
|
let (fa1, fb1) = (a.0 as f64, a.1 as f64);
|
||||||
|
let (fa2, fb2) = (b.0 as f64, b.1 as f64);
|
||||||
|
let (p1, p2) = (prize.0 as f64, prize.1 as f64);
|
||||||
|
|
||||||
|
let y_denominator = fb2 - fb1 * fa2 / fa1;
|
||||||
|
if equal(y_denominator, 0.0, EPS) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let y_nominator = p2 - fb1 * p1 / fa1;
|
||||||
|
if !divisible(y_nominator, y_denominator, EPS) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let x_nominator = p1 - fa2 * (p2 - fb1 * p1 / fa1) / (fb2 - fb1 * fa2 / fa1);
|
||||||
|
if !divisible(x_nominator, fa1, EPS) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let y = (y_nominator / y_denominator).round() as i64;
|
||||||
|
let x = (x_nominator / fa1).round() as i64;
|
||||||
|
|
||||||
|
if x < 0 || y < 0 || x > 100 || y > 100 {
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
return Some(x * 3 + y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn linear_solve_2(a: (i64, i64), b: (i64, i64), prize: (i64, i64)) -> Option<i64> {
|
||||||
|
const EPS: f64 = 0.001;
|
||||||
|
const BONUS: i64 = 10000000000000;
|
||||||
|
|
||||||
|
let (fa1, fb1) = (a.0 as f64, a.1 as f64);
|
||||||
|
let (fa2, fb2) = (b.0 as f64, b.1 as f64);
|
||||||
|
let (p1, p2) = ((prize.0 + BONUS) as f64, (prize.1 + BONUS) as f64);
|
||||||
|
|
||||||
|
let y_denominator = fb2 - fb1 * fa2 / fa1;
|
||||||
|
if equal(y_denominator, 0.0, EPS) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let y_nominator = p2 - fb1 * p1 / fa1;
|
||||||
|
if !divisible(y_nominator, y_denominator, EPS) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let x_nominator = p1 - fa2 * (p2 - fb1 * p1 / fa1) / (fb2 - fb1 * fa2 / fa1);
|
||||||
|
if !divisible(x_nominator, fa1, EPS) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let y = (y_nominator / y_denominator).round() as i64;
|
||||||
|
let x = (x_nominator / fa1).round() as i64;
|
||||||
|
|
||||||
|
if x < 0 || y < 0 {
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
return Some(x * 3 + y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve_1(input: &str) -> i64 {
|
||||||
|
let (_, result) = parse(input).unwrap();
|
||||||
|
|
||||||
|
result
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|(a, b, prize)| linear_solve_1(a, b, prize))
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve_2(input: &str) -> i64 {
|
||||||
|
let (_, result) = parse(input).unwrap();
|
||||||
|
|
||||||
|
result
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|(a, b, prize)| linear_solve_2(a, b, prize))
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, this is Patrick!");
|
||||||
|
|
||||||
|
let input = include_str!("../input.txt");
|
||||||
|
|
||||||
|
let result_1 = solve_1(input);
|
||||||
|
println!("The fewest tokens spent to get all prizes is {}", result_1);
|
||||||
|
|
||||||
|
let result_2 = solve_2(input);
|
||||||
|
println!(
|
||||||
|
"With the huge positions, the fewest tokens to get all prizes is now {}",
|
||||||
|
result_2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_1() {
|
||||||
|
let test_input = include_str!("../test.txt");
|
||||||
|
assert_eq!(solve_1(test_input), 480);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_2() {
|
||||||
|
let test_input = include_str!("../test.txt");
|
||||||
|
let ts = parse(test_input).unwrap().1;
|
||||||
|
|
||||||
|
for (i, t) in ts.into_iter().enumerate() {
|
||||||
|
if i % 2 == 0 {
|
||||||
|
assert!(linear_solve_2(t.0, t.1, t.2).is_none());
|
||||||
|
} else {
|
||||||
|
assert!(linear_solve_2(t.0, t.1, t.2).is_some());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
advent_of_code/2024/13/test.txt
Normal file
15
advent_of_code/2024/13/test.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
Button A: X+94, Y+34
|
||||||
|
Button B: X+22, Y+67
|
||||||
|
Prize: X=8400, Y=5400
|
||||||
|
|
||||||
|
Button A: X+26, Y+66
|
||||||
|
Button B: X+67, Y+21
|
||||||
|
Prize: X=12748, Y=12176
|
||||||
|
|
||||||
|
Button A: X+17, Y+86
|
||||||
|
Button B: X+84, Y+37
|
||||||
|
Prize: X=7870, Y=6450
|
||||||
|
|
||||||
|
Button A: X+69, Y+23
|
||||||
|
Button B: X+27, Y+71
|
||||||
|
Prize: X=18641, Y=10279
|
||||||
Reference in New Issue
Block a user