From 8269af601134a7ce2cdde2d371f3c00c3132602a Mon Sep 17 00:00:00 2001 From: Daniel Lin Date: Sun, 24 Dec 2023 21:46:35 -0500 Subject: [PATCH] Day 24: Never Tell Me The Odds (part 1) --- README.md | 2 +- rs/benches/criterion.rs | 7 +++- rs/src/day24.rs | 77 +++++++++++++++++++++++++++++++++++++++++ rs/src/lib.rs | 1 + rs/src/main.rs | 9 ++++- 5 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 rs/src/day24.rs diff --git a/README.md b/README.md index 1dea7f27..2030e13d 100644 --- a/README.md +++ b/README.md @@ -28,4 +28,4 @@ Development occurs in language-specific directories: |[Day21.hs](hs/src/Day21.hs)|[Day21.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day21.kt)|[day21.py](py/aoc2023/day21.py)|[day21.rs](rs/src/day21.rs)| |[Day22.hs](hs/src/Day22.hs)|[Day22.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day22.kt)|[day22.py](py/aoc2023/day22.py)|[day22.rs](rs/src/day22.rs)| ||[Day23.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day23.kt)||| -|[Day24.hs](hs/src/Day24.hs) ½|[Day24.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day24.kt) ½|[day24.py](py/aoc2023/day24.py) ½|| +|[Day24.hs](hs/src/Day24.hs) ½|[Day24.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day24.kt) ½|[day24.py](py/aoc2023/day24.py) ½|[day24.rs](rs/src/day24.rs) ½| diff --git a/rs/benches/criterion.rs b/rs/benches/criterion.rs index 1dd74099..eaa460f4 100644 --- a/rs/benches/criterion.rs +++ b/rs/benches/criterion.rs @@ -1,6 +1,6 @@ use aoc2023::{ day1, day10, day11, day12, day13, day14, day15, day16, day17, day18, day19, day2, day20, day21, - day22, day3, day4, day5, day6, day7, day8, day9, + day22, day24, day3, day4, day5, day6, day7, day8, day9, }; use criterion::{black_box, Criterion}; use std::env; @@ -149,6 +149,11 @@ fn aoc2023_bench(c: &mut Criterion) -> io::Result<()> { g.bench_function("part 2", |b| b.iter(|| day22::part2(black_box(&data)))); g.finish(); + let data = get_day_input(24)?; + let mut g = c.benchmark_group("day 24"); + g.bench_function("part 1", |b| b.iter(|| day24::part1(black_box(&data)))); + g.finish(); + Ok(()) } diff --git a/rs/src/day24.rs b/rs/src/day24.rs new file mode 100644 index 00000000..10c33321 --- /dev/null +++ b/rs/src/day24.rs @@ -0,0 +1,77 @@ +use std::cmp::Ordering; +use std::ops::RangeInclusive; + +fn part1_internal(data: &str, lo: f64, hi: f64) -> Option { + let mut lines = Vec::<(f64, f64, RangeInclusive)>::new(); + data.lines() + .map(|line| -> Option { + let (pos, vel) = line.split_once('@')?; + let mut iter = pos.splitn(3, ','); + let (x0, y0, _) = ( + iter.next()?.trim().parse::().ok()?, + iter.next()?.trim().parse::().ok()?, + iter.next()?.trim().parse::().ok()?, + ); + let mut iter = vel.splitn(3, ','); + let (vx0, vy0, _) = ( + iter.next()?.trim().parse::().ok()?, + iter.next()?.trim().parse::().ok()?, + iter.next()?.trim().parse::().ok()?, + ); + let m0 = vy0 / vx0; + let b0 = y0 - m0 * x0; + let range0 = match vx0.partial_cmp(&0.0)? { + Ordering::Less => -f64::INFINITY..=x0, + Ordering::Equal => return None, + Ordering::Greater => x0..=f64::INFINITY, + }; + let n = lines + .iter() + .filter(|(m1, b1, range1)| { + let x = (b0 - b1) / (m1 - m0); + m0 != *m1 + && (lo..=hi).contains(&x) + && (lo..=hi).contains(&(m0 * x + b0)) + && range0.contains(&x) + && range1.contains(&x) + }) + .count(); + lines.push((m0, b0, range0)); + Some(n) + }) + .try_fold(0, |acc, n| Some(acc + n?)) +} + +pub fn part1(data: &str) -> Option { + part1_internal(data, 2e14, 4e14) +} + +pub fn part2(_data: &str) -> Option { + None +} + +#[cfg(test)] +mod tests { + use super::*; + use indoc::indoc; + use pretty_assertions::assert_eq; + + static EXAMPLE: &str = indoc! {" + 19, 13, 30 @ -2, 1, -2 + 18, 19, 22 @ -1, -1, -2 + 20, 25, 34 @ -2, -2, -4 + 12, 31, 28 @ -1, -2, -1 + 20, 19, 15 @ 1, -5, -3 + "}; + + #[test] + fn part1_examples() { + assert_eq!(Some(2), part1_internal(EXAMPLE, 7.0, 27.0)); + } + + #[test] + #[ignore] + fn part2_examples() { + assert_eq!(Some(47), part2(EXAMPLE)); + } +} diff --git a/rs/src/lib.rs b/rs/src/lib.rs index fd15337b..01d4c612 100644 --- a/rs/src/lib.rs +++ b/rs/src/lib.rs @@ -13,6 +13,7 @@ pub mod day2; pub mod day20; pub mod day21; pub mod day22; +pub mod day24; pub mod day3; pub mod day4; pub mod day5; diff --git a/rs/src/main.rs b/rs/src/main.rs index ebda170d..49488870 100644 --- a/rs/src/main.rs +++ b/rs/src/main.rs @@ -1,6 +1,6 @@ use aoc2023::{ day1, day10, day11, day12, day13, day14, day15, day16, day17, day18, day19, day2, day20, day21, - day22, day3, day4, day5, day6, day7, day8, day9, + day22, day24, day3, day4, day5, day6, day7, day8, day9, }; use std::collections::HashSet; use std::env; @@ -195,5 +195,12 @@ fn main() -> io::Result<()> { println!(); } + if args.is_empty() || args.contains("24") { + println!("Day 24"); + let data = get_day_input(24)?; + println!("{:?}", day24::part1(&data).expect("error")); + println!(); + } + Ok(()) }