day13 simpler

This commit is contained in:
Jan-Bulthuis 2024-12-14 01:23:15 +01:00
parent 647e2fb356
commit 2cf47fd7d6
1 changed files with 33 additions and 139 deletions

View File

@ -1,16 +1,14 @@
use std::cmp::Ordering;
use aoc_runner_derive::{aoc, aoc_generator}; use aoc_runner_derive::{aoc, aoc_generator};
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::character::complete::{multispace0, u64 as parse_u64}; use nom::character::complete::{i64 as parse_u64, multispace0};
use nom::multi::many0; use nom::multi::many0;
use nom::IResult; use nom::IResult;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
struct Case { struct Case {
button_a: (u64, u64), button_a: (i64, i64),
button_b: (u64, u64), button_b: (i64, i64),
prize: (u64, u64), prize: (i64, i64),
} }
type Input = Vec<Case>; type Input = Vec<Case>;
@ -46,76 +44,25 @@ fn parse_case(input: &str) -> IResult<&str, Case> {
} }
#[aoc(day13, part1)] #[aoc(day13, part1)]
fn part1(input: &Input) -> u64 { fn part1(input: &Input) -> i64 {
input input
.iter() .iter()
.copied() .copied()
.map(|case| { .map(|case| {
let (vec_low, vec_high, cost_low, cost_high) = match (case.button_a.1 * case.button_b.0) let vec_a = case.button_a;
.cmp(&(case.button_a.0 * case.button_b.1)) let vec_b = case.button_b;
let vec_p = case.prize;
if (vec_p.0 * vec_b.1 - vec_b.0 * vec_p.1) % (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1)
== 0
&& (vec_a.0 * vec_p.1 - vec_p.0 * vec_a.1) % (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1)
== 0
{ {
Ordering::Greater => (case.button_b, case.button_a, 1, 3), let a = (vec_p.0 * vec_b.1 - vec_b.0 * vec_p.1)
Ordering::Less => (case.button_a, case.button_b, 3, 1), / (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1);
Ordering::Equal => panic!("Parallel"), let b = (vec_a.0 * vec_p.1 - vec_p.0 * vec_a.1)
}; / (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1);
let vec_prize = case.prize; a * 3 + b
let vec_low_norm = (
vec_low.0 as f64 / ((vec_low.0 * vec_low.0 + vec_low.1 * vec_low.1) as f64).sqrt(),
vec_low.1 as f64 / ((vec_low.0 * vec_low.0 + vec_low.1 * vec_low.1) as f64).sqrt(),
);
let vec_prize_proj = (
vec_low_norm.0
* (vec_prize.0 as f64 * vec_low_norm.0 + vec_prize.1 as f64 * vec_low_norm.1),
vec_low_norm.1
* (vec_prize.0 as f64 * vec_low_norm.0 + vec_prize.1 as f64 * vec_low_norm.1),
);
let vec_prize_perp = (
vec_prize.0 as f64 - vec_prize_proj.0,
vec_prize.1 as f64 - vec_prize_proj.1,
);
let len_prize_perp =
(vec_prize_perp.0 * vec_prize_perp.0 + vec_prize_perp.1 * vec_prize_perp.1).sqrt();
let vec_high_proj = (
vec_low_norm.0
* (vec_high.0 as f64 * vec_low_norm.0 + vec_high.1 as f64 * vec_low_norm.1),
vec_low_norm.1
* (vec_high.0 as f64 * vec_low_norm.0 + vec_high.1 as f64 * vec_low_norm.1),
);
let vec_high_perp = (
vec_high.0 as f64 - vec_high_proj.0,
vec_high.1 as f64 - vec_high_proj.1,
);
let len_high_perp =
(vec_high_perp.0 * vec_high_perp.0 + vec_high_perp.1 * vec_high_perp.1).sqrt();
let n_high = len_prize_perp / len_high_perp;
let vec_low_goal = (
vec_prize.0 as f64 - n_high * vec_high.0 as f64,
vec_prize.1 as f64 - n_high * vec_high.1 as f64,
);
let len_low = ((vec_low.0 * vec_low.0 + vec_low.1 * vec_low.1) as f64).sqrt();
let len_low_goal =
(vec_low_goal.0 * vec_low_goal.0 + vec_low_goal.1 * vec_low_goal.1).sqrt();
let n_low = len_low_goal / len_low;
let n_high = n_high.round() as u64;
let n_low = n_low.round() as u64;
if n_high * vec_high.0 + n_low * vec_low.0 == vec_prize.0
&& n_high * vec_high.1 + n_low * vec_low.1 == vec_prize.1
{
n_high * cost_high + n_low * cost_low
} else { } else {
0 0
} }
@ -124,79 +71,26 @@ fn part1(input: &Input) -> u64 {
} }
#[aoc(day13, part2)] #[aoc(day13, part2)]
fn part2(input: &Input) -> u64 { fn part2(input: &Input) -> i64 {
input input
.iter() .iter()
.copied() .copied()
.map(|case| { .map(|case| {
let (vec_low, vec_high, cost_low, cost_high) = match (case.button_a.1 * case.button_b.0) let vec_a = case.button_a;
.cmp(&(case.button_a.0 * case.button_b.1)) let vec_b = case.button_b;
let vec_p = case.prize;
let vec_p = (vec_p.0 + 10_000_000_000_000, vec_p.1 + 10_000_000_000_000);
if (vec_p.0 * vec_b.1 - vec_b.0 * vec_p.1) % (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1)
== 0
&& (vec_a.0 * vec_p.1 - vec_p.0 * vec_a.1) % (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1)
== 0
{ {
Ordering::Greater => (case.button_b, case.button_a, 1, 3), let a = (vec_p.0 * vec_b.1 - vec_b.0 * vec_p.1)
Ordering::Less => (case.button_a, case.button_b, 3, 1), / (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1);
Ordering::Equal => panic!("Parallel"), let b = (vec_a.0 * vec_p.1 - vec_p.0 * vec_a.1)
}; / (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1);
let vec_prize = ( a * 3 + b
case.prize.0 + 10_000_000_000_000,
case.prize.1 + 10_000_000_000_000,
);
let vec_low_norm = (
vec_low.0 as f64 / ((vec_low.0 * vec_low.0 + vec_low.1 * vec_low.1) as f64).sqrt(),
vec_low.1 as f64 / ((vec_low.0 * vec_low.0 + vec_low.1 * vec_low.1) as f64).sqrt(),
);
let vec_prize_proj = (
vec_low_norm.0
* (vec_prize.0 as f64 * vec_low_norm.0 + vec_prize.1 as f64 * vec_low_norm.1),
vec_low_norm.1
* (vec_prize.0 as f64 * vec_low_norm.0 + vec_prize.1 as f64 * vec_low_norm.1),
);
let vec_prize_perp = (
vec_prize.0 as f64 - vec_prize_proj.0,
vec_prize.1 as f64 - vec_prize_proj.1,
);
let len_prize_perp =
(vec_prize_perp.0 * vec_prize_perp.0 + vec_prize_perp.1 * vec_prize_perp.1).sqrt();
let vec_high_proj = (
vec_low_norm.0
* (vec_high.0 as f64 * vec_low_norm.0 + vec_high.1 as f64 * vec_low_norm.1),
vec_low_norm.1
* (vec_high.0 as f64 * vec_low_norm.0 + vec_high.1 as f64 * vec_low_norm.1),
);
let vec_high_perp = (
vec_high.0 as f64 - vec_high_proj.0,
vec_high.1 as f64 - vec_high_proj.1,
);
let len_high_perp =
(vec_high_perp.0 * vec_high_perp.0 + vec_high_perp.1 * vec_high_perp.1).sqrt();
let n_high = len_prize_perp / len_high_perp;
let vec_low_goal = (
vec_prize.0 as f64 - n_high * vec_high.0 as f64,
vec_prize.1 as f64 - n_high * vec_high.1 as f64,
);
let len_low = ((vec_low.0 * vec_low.0 + vec_low.1 * vec_low.1) as f64).sqrt();
let len_low_goal =
(vec_low_goal.0 * vec_low_goal.0 + vec_low_goal.1 * vec_low_goal.1).sqrt();
let n_low = len_low_goal / len_low;
let n_high = n_high.round() as u64;
let n_low = n_low.round() as u64;
if n_high * vec_high.0 + n_low * vec_low.0 == vec_prize.0
&& n_high * vec_high.1 + n_low * vec_low.1 == vec_prize.1
{
n_high * cost_high + n_low * cost_low
} else { } else {
0 0
} }