diff --git a/2025/Cargo.lock b/2025/Cargo.lock index f153b5a..fa6ab88 100644 --- a/2025/Cargo.lock +++ b/2025/Cargo.lock @@ -190,6 +190,21 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "day-07" +version = "0.1.0" +dependencies = [ + "divan", + "itertools", + "miette", + "nom", + "rstest", + "test-log", + "thiserror", + "tracing", + "tracing-subscriber", +] + [[package]] name = "divan" version = "0.1.21" diff --git a/2025/day-07/src/part1.rs b/2025/day-07/src/part1.rs index 1639d01..0f2cad4 100644 --- a/2025/day-07/src/part1.rs +++ b/2025/day-07/src/part1.rs @@ -1,9 +1,65 @@ +use std::collections::HashSet; +use tracing::info; + +type Column = usize; +type Row = usize; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +struct Splitter { + column: Column, + row: Row, +} + +#[derive(Debug)] +struct SimulationState { + active_positions: HashSet, + splitters: HashSet, +} + +impl SimulationState { + fn new(start_column: Column) -> Self { + let mut active_positions = HashSet::new(); + active_positions.insert(start_column); + Self { + active_positions, + splitters: HashSet::new(), + } + } + + fn process_row(&mut self, row: Row, line: &str) { + let mut next_positions = HashSet::new(); + + for col in &self.active_positions { + if line.as_bytes()[*col] == b'^' { + info!(?col, "split at"); + next_positions.insert(col - 1); + next_positions.insert(col + 1); + next_positions.insert(col + 1); + self.splitters.insert(Splitter { column: *col, row }); + } else { + next_positions.insert(*col); + } + } + + self.active_positions = next_positions; + } +} + #[tracing::instrument] #[allow(clippy::missing_panics_doc)] #[allow(clippy::missing_errors_doc)] pub fn process(input: &str) -> miette::Result { - todo!("day xx - part 1"); - Ok(0) + let mut lines = input.lines().enumerate(); + let (_, first_line) = lines.next().unwrap(); + let start_column = first_line.chars().position(|ch| ch == 'S').unwrap(); + + let mut state = SimulationState::new(start_column); + + for (row, line) in lines { + state.process_row(row, line); + } + + Ok(state.splitters.len()) } #[cfg(test)] @@ -12,9 +68,24 @@ mod tests { #[test] fn test_process() -> miette::Result<()> { - let input = ""; - todo!("haven't built test yet"); - let result = 0; + let input = ".......S....... +............... +.......^....... +............... +......^.^...... +............... +.....^.^.^..... +............... +....^.^...^.... +............... +...^.^...^.^... +............... +..^...^.....^.. +............... +.^.^.^.^.^...^. +............... +"; + let result = 21; assert_eq!(process(input)?, result); Ok(()) }