From 2cf47fd7d671b0a330e4158becc0d439fa0e0b3c Mon Sep 17 00:00:00 2001 From: Jan-Bulthuis Date: Sat, 14 Dec 2024 01:23:15 +0100 Subject: [PATCH] day13 simpler --- aoc_2024/src/day13.rs | 172 ++++++++---------------------------------- 1 file changed, 33 insertions(+), 139 deletions(-) diff --git a/aoc_2024/src/day13.rs b/aoc_2024/src/day13.rs index 99e8eb3..20a5747 100644 --- a/aoc_2024/src/day13.rs +++ b/aoc_2024/src/day13.rs @@ -1,16 +1,14 @@ -use std::cmp::Ordering; - use aoc_runner_derive::{aoc, aoc_generator}; 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::IResult; #[derive(Debug, Clone, Copy)] struct Case { - button_a: (u64, u64), - button_b: (u64, u64), - prize: (u64, u64), + button_a: (i64, i64), + button_b: (i64, i64), + prize: (i64, i64), } type Input = Vec; @@ -46,76 +44,25 @@ fn parse_case(input: &str) -> IResult<&str, Case> { } #[aoc(day13, part1)] -fn part1(input: &Input) -> u64 { +fn part1(input: &Input) -> i64 { input .iter() .copied() .map(|case| { - let (vec_low, vec_high, cost_low, cost_high) = match (case.button_a.1 * case.button_b.0) - .cmp(&(case.button_a.0 * case.button_b.1)) + let vec_a = case.button_a; + 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), - Ordering::Less => (case.button_a, case.button_b, 3, 1), - Ordering::Equal => panic!("Parallel"), - }; - let vec_prize = case.prize; - - 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 + let a = (vec_p.0 * vec_b.1 - vec_b.0 * vec_p.1) + / (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1); + 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); + a * 3 + b } else { 0 } @@ -124,79 +71,26 @@ fn part1(input: &Input) -> u64 { } #[aoc(day13, part2)] -fn part2(input: &Input) -> u64 { +fn part2(input: &Input) -> i64 { input .iter() .copied() .map(|case| { - let (vec_low, vec_high, cost_low, cost_high) = match (case.button_a.1 * case.button_b.0) - .cmp(&(case.button_a.0 * case.button_b.1)) + let vec_a = case.button_a; + 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), - Ordering::Less => (case.button_a, case.button_b, 3, 1), - Ordering::Equal => panic!("Parallel"), - }; - let vec_prize = ( - 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 + let a = (vec_p.0 * vec_b.1 - vec_b.0 * vec_p.1) + / (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1); + 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); + a * 3 + b } else { 0 }