day6: performance improvement
This commit is contained in:
parent
145d779e83
commit
1dd3ce5862
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
input
|
input
|
||||||
flamegraph.svg
|
flamegraph.svg
|
||||||
perf.data
|
perf.data
|
||||||
|
guesses
|
||||||
|
7
6/Cargo.lock
generated
7
6/Cargo.lock
generated
@ -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",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -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" }
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user