From 89f2b849ad7f796a554f2da992ebef190877eeb4 Mon Sep 17 00:00:00 2001 From: Burnus Date: Mon, 18 Aug 2025 18:56:02 +0200 Subject: [PATCH] 2023 Day 16 Performance Improvements --- 2023/day16_the_floor_will_be_lava/src/lib.rs | 41 ++++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/2023/day16_the_floor_will_be_lava/src/lib.rs b/2023/day16_the_floor_will_be_lava/src/lib.rs index 779cce5..9b86e0b 100644 --- a/2023/day16_the_floor_will_be_lava/src/lib.rs +++ b/2023/day16_the_floor_will_be_lava/src/lib.rs @@ -1,5 +1,5 @@ use core::fmt::Display; -use std::collections::{HashMap, BTreeSet}; +use std::collections::{HashMap, BTreeSet, HashSet}; #[derive(Debug, PartialEq, Eq)] pub enum ParseError { @@ -16,8 +16,14 @@ impl Display for ParseError { } } +#[derive(PartialEq, Eq, Hash)] +struct StartingCondition { + starting_tile: (usize, usize), + starting_direction: Direction, +} + #[repr(u8)] -#[derive(PartialEq)] +#[derive(PartialEq, Eq, Hash, Clone, Copy)] enum Direction { North = 0b0001, West = 0b0010, @@ -118,7 +124,13 @@ impl TryFrom<&str> for Grid { } impl Grid { - fn get_energized(&self, starting_tile: (usize, usize), starting_direction: Direction) -> usize { + fn get_energized(&self, starting_tile: (usize, usize), starting_direction: Direction, seen: &mut HashSet) -> usize { + let sc = StartingCondition { starting_tile, starting_direction, }; + if seen.contains(&sc) { + return 0; + } else { + seen.insert(sc); + } let mut energized: HashMap<(usize, usize), u8> = HashMap::from([(starting_tile, starting_direction.as_u8())]); let mut open_set = BTreeSet::from([starting_tile]); while let Some((x, y)) = open_set.pop_last() { @@ -148,6 +160,18 @@ impl Grid { _ => unreachable!(), }; } + if x == 0 && directions.contains(&Direction::West) { + seen.insert(StartingCondition{ starting_tile: (x, y), starting_direction: Direction::East }); + } + if y == 0 && directions.contains(&Direction::North) { + seen.insert(StartingCondition{ starting_tile: (x, y), starting_direction: Direction::South }); + } + if x == self.max.0 && directions.contains(&Direction::East) { + seen.insert(StartingCondition{ starting_tile: (x, y), starting_direction: Direction::West }); + } + if y == self.max.1 && directions.contains(&Direction::South) { + seen.insert(StartingCondition{ starting_tile: (x, y), starting_direction: Direction::North }); + } for direction in directions { if let Some(neighbour) = direction.next_from(x, y) { if neighbour.0 <= self.max.0 && neighbour.1 <= self.max.1 { @@ -168,11 +192,12 @@ impl Grid { pub fn run(input: &str) -> Result<(usize, usize), ParseError> { let grid = Grid::try_from(input)?; - let first = grid.get_energized((0,0), Direction::East); - let second = (0..grid.max.0).map(|x| grid.get_energized((x, 0), Direction::South)).max().unwrap_or(0).max( - (0..grid.max.0).map(|x| grid.get_energized((x, grid.max.1), Direction::North)).max().unwrap_or(0).max( - (0..grid.max.1).map(|y| grid.get_energized((0, y), Direction::East)).max().unwrap_or(0).max( - (0..grid.max.1).map(|y| grid.get_energized((grid.max.0, y), Direction::West)).max().unwrap_or(0) + let first = grid.get_energized((0,0), Direction::East, &mut HashSet::new()); + let mut seen = HashSet::new(); + let second = (0..grid.max.0).map(|x| grid.get_energized((x, 0), Direction::South, &mut seen)).max().unwrap_or(0).max( + (0..grid.max.0).map(|x| grid.get_energized((x, grid.max.1), Direction::North, &mut seen)).max().unwrap_or(0).max( + (0..grid.max.1).map(|y| grid.get_energized((0, y), Direction::East, &mut seen)).max().unwrap_or(0).max( + (0..grid.max.1).map(|y| grid.get_energized((grid.max.0, y), Direction::West, &mut seen)).max().unwrap_or(0) ))); Ok((first, second)) }