From f34e61c4b007c90e8c4934109f86078e3aef50ed Mon Sep 17 00:00:00 2001 From: Daniel Lin Date: Sun, 8 Dec 2024 02:17:57 -0500 Subject: [PATCH] Day 8: Resonant Collinearity --- README.md | 2 +- rs/benches/criterion.rs | 8 +++- rs/src/day8.rs | 90 +++++++++++++++++++++++++++++++++++++++++ rs/src/lib.rs | 1 + rs/src/main.rs | 10 ++++- 5 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 rs/src/day8.rs diff --git a/README.md b/README.md index 81a0fcee..c75a6883 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,4 @@ Development occurs in language-specific directories: |[Day5.hs](hs/src/Day5.hs)|[Day5.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day5.kt)|[day5.py](py/aoc2024/day5.py)|[day5.rs](rs/src/day5.rs)| |[Day6.hs](hs/src/Day6.hs)|[Day6.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day6.kt)|[day6.py](py/aoc2024/day6.py)|[day6.rs](rs/src/day6.rs)| |[Day7.hs](hs/src/Day7.hs)|[Day7.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day7.kt)|[day7.py](py/aoc2024/day7.py)|[day7.rs](rs/src/day7.rs)| -|[Day8.hs](hs/src/Day8.hs)|[Day8.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day8.kt)|[day8.py](py/aoc2024/day8.py)|| +|[Day8.hs](hs/src/Day8.hs)|[Day8.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day8.kt)|[day8.py](py/aoc2024/day8.py)|[day8.rs](rs/src/day8.rs)| diff --git a/rs/benches/criterion.rs b/rs/benches/criterion.rs index d946b4d9..b454fb08 100644 --- a/rs/benches/criterion.rs +++ b/rs/benches/criterion.rs @@ -1,4 +1,4 @@ -use aoc2024::{day1, day2, day3, day4, day5, day6, day7}; +use aoc2024::{day1, day2, day3, day4, day5, day6, day7, day8}; use criterion::{black_box, Criterion}; use std::env; use std::fs; @@ -56,6 +56,12 @@ fn aoc2024_bench(c: &mut Criterion) -> io::Result<()> { g.bench_function("part 2", |b| b.iter(|| day7::part2(black_box(&data)))); g.finish(); + let data = get_day_input(8)?; + let mut g = c.benchmark_group("day 8"); + g.bench_function("part 1", |b| b.iter(|| day8::part1(black_box(&data)))); + g.bench_function("part 2", |b| b.iter(|| day8::part2(black_box(&data)))); + g.finish(); + Ok(()) } diff --git a/rs/src/day8.rs b/rs/src/day8.rs new file mode 100644 index 00000000..ddd42135 --- /dev/null +++ b/rs/src/day8.rs @@ -0,0 +1,90 @@ +use std::collections::BTreeSet; +use std::iter; + +use itertools::Itertools; + +fn solve(data: &str, multiples: I) -> usize +where + I: Clone + Iterator, +{ + let (mut height, mut width) = (0, 0); + data.lines() + .enumerate() + .flat_map(|(y, line)| { + height = y + 1; + width = width.max(line.len()); + line.bytes().enumerate().filter_map(move |(x, b)| match b { + b'.' => None, + _ => Some((b, (y, x))), + }) + }) + .into_grouping_map_by(|(b, _)| *b) + .fold_with( + |_, _| vec![], + |mut acc, _, (_, point)| { + acc.push(point); + acc + }, + ) + .values() + .flat_map(|points| { + points.iter().flat_map(|point0 @ (y0, x0)| { + points + .iter() + .filter(move |point1| point0 != *point1) + .flat_map(|(y1, x1)| { + let (dy, dx) = (*y1 as isize - *y0 as isize, *x1 as isize - *x0 as isize); + multiples + .clone() + .map(move |i| { + y1.checked_add_signed(i * dy) + .filter(|y| *y < height) + .zip(x1.checked_add_signed(i * dx).filter(|x| *x < width)) + }) + .while_some() + }) + }) + }) + .collect::>() + .len() +} + +pub fn part1(data: &str) -> usize { + solve(data, iter::once(1)) +} + +pub fn part2(data: &str) -> usize { + solve(data, iter::successors(Some(0), |i| Some(i + 1))) +} + +#[cfg(test)] +mod tests { + use super::*; + use indoc::indoc; + use pretty_assertions::assert_eq; + + static EXAMPLE: &str = indoc! {" + ............ + ........0... + .....0...... + .......0.... + ....0....... + ......A..... + ............ + ............ + ........A... + .........A.. + ............ + ............ + "}; + + #[test] + fn part1_examples() { + assert_eq!(14, part1(EXAMPLE)); + } + + #[test] + fn part2_examples() { + assert_eq!(34, part2(EXAMPLE)); + } +} diff --git a/rs/src/lib.rs b/rs/src/lib.rs index da2f9142..65fdb47f 100644 --- a/rs/src/lib.rs +++ b/rs/src/lib.rs @@ -5,3 +5,4 @@ pub mod day4; pub mod day5; pub mod day6; pub mod day7; +pub mod day8; diff --git a/rs/src/main.rs b/rs/src/main.rs index 0c506941..5aa1c058 100644 --- a/rs/src/main.rs +++ b/rs/src/main.rs @@ -1,5 +1,5 @@ use anyhow::anyhow; -use aoc2024::{day1, day2, day3, day4, day5, day6, day7}; +use aoc2024::{day1, day2, day3, day4, day5, day6, day7, day8}; use std::collections::HashSet; use std::env; use std::fs; @@ -73,5 +73,13 @@ fn main() -> anyhow::Result<()> { println!(); } + if args.is_empty() || args.contains("8") { + println!("Day 8"); + let data = get_day_input(8)?; + println!("{:?}", day8::part1(&data)); + println!("{:?}", day8::part2(&data)); + println!(); + } + Ok(()) }