From ca302578c9083da72b93dc09e87a931da4c91d52 Mon Sep 17 00:00:00 2001 From: Russell Champoux Date: Tue, 9 Dec 2025 15:57:20 -0500 Subject: [PATCH] Solve Day 7: Tachyon beam splits and quantum timelines --- README.md | 3 +- data/examples/07.txt | 17 ++++++ src/bin/07.rs | 132 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 data/examples/07.txt create mode 100644 src/bin/07.rs diff --git a/README.md b/README.md index d82020c..2c8d7e8 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www. | [Day 4](./src/bin/04.rs) | `244.2µs` | `4.1ms` | | [Day 5](./src/bin/05.rs) | `196.7µs` | `66.3µs` | | [Day 6](./src/bin/06.rs) | `109.0µs` | `194.2µs` | +| [Day 7](./src/bin/07.rs) | `270.5µs` | `320.2µs` | -**Total: 5.79ms** +**Total: 6.38ms** --- diff --git a/data/examples/07.txt b/data/examples/07.txt new file mode 100644 index 0000000..5c4186a --- /dev/null +++ b/data/examples/07.txt @@ -0,0 +1,17 @@ +.......S....... +............... +.......^....... +............... +......^.^...... +............... +.....^.^.^..... +............... +....^.^...^.... +............... +...^.^...^.^... +............... +..^...^.....^.. +............... +.^.^.^.^.^...^. +............... + diff --git a/src/bin/07.rs b/src/bin/07.rs new file mode 100644 index 0000000..e856bba --- /dev/null +++ b/src/bin/07.rs @@ -0,0 +1,132 @@ +use std::collections::{HashMap, HashSet}; + +advent_of_code::solution!(7); + +/// Parse the grid and find the starting column +fn parse_grid(input: &str) -> (Vec>, usize) { + let grid: Vec> = input + .lines() + .filter(|l| !l.is_empty()) + .map(|l| l.chars().collect()) + .collect(); + + let start_col = grid[0] + .iter() + .position(|&c| c == 'S') + .expect("No starting position 'S' found"); + + (grid, start_col) +} + +/// Simulate tachyon beams through the manifold and count splits +/// Beams merge when they occupy the same column (HashSet) +fn count_splits(input: &str) -> u64 { + let (grid, start_col) = parse_grid(input); + if grid.is_empty() { + return 0; + } + + let width = grid[0].len(); + let mut beams: HashSet = HashSet::new(); + beams.insert(start_col); + + let mut split_count: u64 = 0; + + for row in grid.iter().skip(1) { + let mut new_beams: HashSet = HashSet::new(); + + for &col in &beams { + match row[col] { + '^' => { + split_count += 1; + if col > 0 { + new_beams.insert(col - 1); + } + if col + 1 < width { + new_beams.insert(col + 1); + } + } + _ => { + new_beams.insert(col); + } + } + } + + beams = new_beams; + if beams.is_empty() { + break; + } + } + + split_count +} + +/// Count the number of unique timelines (paths) through the manifold +/// Each particle at a position represents independent timelines - they don't merge +fn count_timelines(input: &str) -> u64 { + let (grid, start_col) = parse_grid(input); + if grid.is_empty() { + return 0; + } + + let width = grid[0].len(); + + // Track number of particles (timelines) at each column position + let mut particles: HashMap = HashMap::new(); + particles.insert(start_col, 1); + + for row in grid.iter().skip(1) { + let mut new_particles: HashMap = HashMap::new(); + + for (&col, &count) in &particles { + match row[col] { + '^' => { + // Each particle splits into 2 timelines (left and right) + if col > 0 { + *new_particles.entry(col - 1).or_insert(0) += count; + } + if col + 1 < width { + *new_particles.entry(col + 1).or_insert(0) += count; + } + } + _ => { + // Particle continues straight down + *new_particles.entry(col).or_insert(0) += count; + } + } + } + + particles = new_particles; + if particles.is_empty() { + break; + } + } + + // Sum all particles - each represents a unique timeline + particles.values().sum() +} + +pub fn part_one(input: &str) -> Option { + Some(count_splits(input)) +} + +pub fn part_two(input: &str) -> Option { + Some(count_timelines(input)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = part_one(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(21)); + } + + #[test] + fn test_part_two() { + let result = part_two(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(40)); + } +}