day6: performance improvement

This commit is contained in:
Keenan Tims 2024-12-06 10:40:28 -08:00
parent 145d779e83
commit 1dd3ce5862
Signed by: ktims
GPG Key ID: 11230674D69038D4
4 changed files with 59 additions and 9 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
input input
flamegraph.svg flamegraph.svg
perf.data perf.data
guesses

7
6/Cargo.lock generated
View File

@ -2,10 +2,17 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]] [[package]]
name = "day6" name = "day6"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bitflags",
"grid", "grid",
] ]

View File

@ -4,4 +4,5 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
bitflags = "2.6.0"
grid = { version = "0.1.0", path = "../libs/grid" } grid = { version = "0.1.0", path = "../libs/grid" }

View File

@ -1,7 +1,9 @@
use bitflags::bitflags;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fmt::Display; use std::fmt;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Lines}; use std::io::{BufRead, BufReader, Lines};
use std::ops::BitAnd;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
// BOILERPLATE // BOILERPLATE
@ -76,10 +78,44 @@ enum RunOutcome {
Stuck, Stuck,
} }
bitflags! {
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct DirectionSet: u8 {
const Up = 1;
const Down = 2;
const Left = 4;
const Right = 8;
}
}
impl From<FacingDirection> for DirectionSet {
fn from(value: FacingDirection) -> Self {
match value {
FacingDirection::Up => DirectionSet::Up,
FacingDirection::Down => DirectionSet::Down,
FacingDirection::Left => DirectionSet::Left,
FacingDirection::Right => DirectionSet::Right,
}
}
}
impl fmt::Display for DirectionSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl BitAnd<FacingDirection> for DirectionSet {
type Output = DirectionSet;
fn bitand(self, rhs: FacingDirection) -> Self::Output {
self & DirectionSet::from(rhs)
}
}
#[derive(Clone)] #[derive(Clone)]
struct Map { struct Map {
grid: grid::Grid<u8>, grid: grid::Grid<u8>,
visited_from: HashMap<(i64, i64), HashSet<FacingDirection>>, visited_from: grid::Grid<DirectionSet>,
guard_facing: FacingDirection, guard_facing: FacingDirection,
guard_pos: (i64, i64), guard_pos: (i64, i64),
} }
@ -87,7 +123,8 @@ struct Map {
impl<T: BufRead> From<Lines<T>> for Map { impl<T: BufRead> From<Lines<T>> for Map {
fn from(input: Lines<T>) -> Self { fn from(input: Lines<T>) -> Self {
let grid = grid::Grid::from(input); let grid = grid::Grid::from(input);
let visited_from = HashMap::new(); let mut visited_from: grid::Grid<DirectionSet> = grid::Grid::new(grid.width() as i64);
visited_from.data.resize(grid.data.len(), DirectionSet::empty());
let guard_pos = grid.find(b'^').expect("Guard not found"); let guard_pos = grid.find(b'^').expect("Guard not found");
let guard_facing = FacingDirection::Up; let guard_facing = FacingDirection::Up;
Self { Self {
@ -111,14 +148,19 @@ impl Map {
/// Move one step in the facing direction, return if we are still inside the bounds /// Move one step in the facing direction, return if we are still inside the bounds
fn step_guard(&mut self) -> StepOutcome { fn step_guard(&mut self) -> StepOutcome {
let new_pos = self.guard_facing.pos_ofs(self.guard_pos); let new_pos = self.guard_facing.pos_ofs(self.guard_pos);
if self.visited_from.contains_key(&new_pos) && self.visited_from[&new_pos].contains(&self.guard_facing) { if self
.visited_from
.get(new_pos.0, new_pos.1)
.is_some_and(|dirs| dirs.contains(self.guard_facing.into()))
{
return StepOutcome::LoopFound; return StepOutcome::LoopFound;
} }
if self.grid.set(new_pos.0, new_pos.1, b'X') { if self.grid.set(new_pos.0, new_pos.1, b'X') {
self.visited_from self.visited_from.set(
.entry(new_pos) new_pos.0,
.or_insert(HashSet::new()) new_pos.1,
.insert(self.guard_facing); self.visited_from.get(new_pos.0, new_pos.1).unwrap() | self.guard_facing.into(),
);
self.guard_pos = new_pos; self.guard_pos = new_pos;
StepOutcome::Continue StepOutcome::Continue
} else { } else {
@ -157,7 +199,6 @@ impl Map {
StepOutcome::LoopFound => return RunOutcome::LoopFound, StepOutcome::LoopFound => return RunOutcome::LoopFound,
StepOutcome::Continue => {} StepOutcome::Continue => {}
}, },
} }
} }
return RunOutcome::LeftMap; return RunOutcome::LeftMap;