2023 Day 16 Performance Improvements

This commit is contained in:
Burnus 2025-08-18 18:56:02 +02:00
parent bf4577f6e0
commit 89f2b849ad

View file

@ -1,5 +1,5 @@
use core::fmt::Display; use core::fmt::Display;
use std::collections::{HashMap, BTreeSet}; use std::collections::{HashMap, BTreeSet, HashSet};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum ParseError { 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)] #[repr(u8)]
#[derive(PartialEq)] #[derive(PartialEq, Eq, Hash, Clone, Copy)]
enum Direction { enum Direction {
North = 0b0001, North = 0b0001,
West = 0b0010, West = 0b0010,
@ -118,7 +124,13 @@ impl TryFrom<&str> for Grid {
} }
impl 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<StartingCondition>) -> 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 energized: HashMap<(usize, usize), u8> = HashMap::from([(starting_tile, starting_direction.as_u8())]);
let mut open_set = BTreeSet::from([starting_tile]); let mut open_set = BTreeSet::from([starting_tile]);
while let Some((x, y)) = open_set.pop_last() { while let Some((x, y)) = open_set.pop_last() {
@ -148,6 +160,18 @@ impl Grid {
_ => unreachable!(), _ => 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 { for direction in directions {
if let Some(neighbour) = direction.next_from(x, y) { if let Some(neighbour) = direction.next_from(x, y) {
if neighbour.0 <= self.max.0 && neighbour.1 <= self.max.1 { 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> { pub fn run(input: &str) -> Result<(usize, usize), ParseError> {
let grid = Grid::try_from(input)?; let grid = Grid::try_from(input)?;
let first = grid.get_energized((0,0), Direction::East); let first = grid.get_energized((0,0), Direction::East, &mut HashSet::new());
let second = (0..grid.max.0).map(|x| grid.get_energized((x, 0), Direction::South)).max().unwrap_or(0).max( let mut seen = HashSet::new();
(0..grid.max.0).map(|x| grid.get_energized((x, grid.max.1), Direction::North)).max().unwrap_or(0).max( 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.1).map(|y| grid.get_energized((0, y), Direction::East)).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((grid.max.0, y), Direction::West)).max().unwrap_or(0) (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)) Ok((first, second))
} }