diff --git a/src/bin/day7.rs b/src/bin/day7.rs new file mode 100644 index 0000000..73a2112 --- /dev/null +++ b/src/bin/day7.rs @@ -0,0 +1,120 @@ +use std::time::Instant; + +use aoc_2025::{Grid, load, print_res}; +use bstr::{BString, ByteSlice}; +use color_eyre::eyre::ContextCompat; + +#[derive(PartialEq, Eq, Debug)] +pub enum ManifoldEntry { + Start, + Empty, + Splitter, +} + +impl std::fmt::Display for ManifoldEntry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ManifoldEntry::Start => write!(f, "S"), + ManifoldEntry::Empty => write!(f, "."), + ManifoldEntry::Splitter => write!(f, "^"), + } + } +} + +type Parsed = Grid; + +#[inline(never)] +pub fn parsing(input: &BString) -> color_eyre::Result { + let line_len = input.find(b"\n").with_context(|| "No newline found")?; + + Ok(Grid::new( + input + .iter() + .filter(|&&v| v != b'\n') + .map(|&v| match v { + b'S' => Ok(ManifoldEntry::Start), + b'.' => Ok(ManifoldEntry::Empty), + b'^' => Ok(ManifoldEntry::Splitter), + _ => color_eyre::eyre::bail!("Invalid splitter entry: {}", v as char), + }) + .collect::>()?, + line_len, + )) +} + +fn manifold_traversal(manifold: &Grid) -> (u64, u64) { + let mut lines = manifold.lines(); + let start_line = lines.next().unwrap(); + let start = start_line + .iter() + .position(|v| *v == ManifoldEntry::Start) + .unwrap(); + + let mut split_count = 0; + + let mut beams = vec![0; start_line.len()]; + beams[start] = 1; + + loop { + let Some(line) = lines.next() else { + break; + }; + + assert!(line.iter().all(|v| *v == ManifoldEntry::Empty)); + + let Some(line) = lines.next() else { + break; + }; + + let mut new_beams = vec![0; start_line.len()]; + + for (beam, count) in beams.iter().enumerate().filter(|&(_, &v)| v != 0) { + match &line[beam] { + ManifoldEntry::Start => panic!("Multiple starts"), + ManifoldEntry::Empty => new_beams[beam] += count, + ManifoldEntry::Splitter => { + split_count += 1; + new_beams[beam - 1] += count; + new_beams[beam + 1] += count; + } + } + } + + beams = new_beams; + } + + (split_count, beams.iter().sum()) +} + +#[inline(never)] +pub fn part1(input: Parsed) { + let (split_count, _) = manifold_traversal(&input); + print_res!("Split count: {split_count}"); +} + +#[inline(never)] +pub fn part2(input: Parsed) { + let (_, path_count) = manifold_traversal(&input); + print_res!("Path count: {path_count}"); +} + +pub fn main() -> color_eyre::Result<()> { + let context = load()?; + + let start = Instant::now(); + let parsed = parsing(&context.input)?; + let elapsed = humantime::format_duration(start.elapsed()); + + let start = Instant::now(); + if context.part == 1 { + part1(parsed); + } else { + part2(parsed); + } + let elapsed_part = humantime::format_duration(start.elapsed()); + + println!(" Parsing: {elapsed}"); + println!(" Solving: {elapsed_part}"); + + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index 292986a..264dc84 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,6 +41,14 @@ impl Grid { (0..line_len).flat_map(move |l| (0..col_len).map(move |c| (l, c))) } + + pub fn line(&self, index: usize) -> &[T] { + &self.values[index * self.line_len..(index + 1) * self.line_len] + } + + pub fn lines(&self) -> impl Iterator { + (0..self.col_len).map(|i| self.line(i)) + } } impl Grid {