Skip to content

Commit 077bba6

Browse files
committed
Probably as fast as this reasonably gets idk
1 parent 7293da6 commit 077bba6

File tree

1 file changed

+20
-17
lines changed

1 file changed

+20
-17
lines changed

2019/src/challenges/day18.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
use std::{
2-
collections::VecDeque,
3-
hash::Hash,
4-
ops::{Bound, RangeBounds},
5-
str::FromStr,
2+
collections::{BinaryHeap, VecDeque}, hash::Hash, ops::{Bound, RangeBounds}, str::FromStr
63
};
74

85
use anyhow::{Result, anyhow};
@@ -196,10 +193,6 @@ impl FromStr for Grid {
196193
}
197194
}
198195

199-
// I am aware that dist has no need to belong in this struct (the first 16 bits right now)
200-
// But for some reason removing it decreases performances (2ms -> 8ms), this is obviously
201-
// stupid: I am litterally removing code, but I guess this changes how the queue behaves
202-
// (it really shouldn't but whatever).
203196
#[derive(Debug, Clone, Copy, Eq)]
204197
struct State<const R: usize> {
205198
inner: u64,
@@ -233,6 +226,15 @@ impl<const R: usize> State<R> {
233226
}
234227
}
235228
#[inline(always)]
229+
fn with_dist(self, dist: usize) -> Self {
230+
debug_assert!(dist <= 65535);
231+
Self { inner: (self.inner & !0xFFFF) | dist as u64 }
232+
}
233+
#[inline(always)]
234+
fn dist(self) -> usize {
235+
(self.inner & 0xFFFF) as usize
236+
}
237+
#[inline(always)]
236238
fn keys(self) -> BitSet {
237239
BitSet {
238240
inner: (self.inner >> 16 & 0x7FFFFFF) as u32,
@@ -247,7 +249,7 @@ impl<const R: usize> State<R> {
247249
impl<const R: usize> PartialEq for State<R> {
248250
#[inline(always)]
249251
fn eq(&self, other: &Self) -> bool {
250-
(self.inner ^ other.inner) >> 16 == 0
252+
self.inner >> 16 == other.inner >> 16
251253
}
252254
}
253255

@@ -409,21 +411,21 @@ impl<const R: usize> KeyGraph<R> {
409411

410412
fn explore(&self) -> usize {
411413
// Dijkstra on the simplified graph
412-
let mut queue = PriorityQueue::new();
414+
let mut queue = BinaryHeap::new();
413415
let mut dist = FxHashMap::with_capacity_and_hasher(131071, FxBuildHasher::default());
414416
let start = State::new(0, [self.count; R], BitSet::empty());
415417
dist.insert(start, 0);
416-
queue.push(0, start);
418+
queue.push(start);
417419

418420
let goal = BitSet::from_range(0..self.count);
419421

420-
while let Some((d, state)) = queue.pop() {
422+
while let Some(state) = queue.pop() {
421423
if state.keys().contains_set(&goal) {
422-
return d;
424+
return state.dist();
423425
}
424426

425427
let c_dist = dist[&state];
426-
if d > c_dist {
428+
if state.dist() > c_dist {
427429
continue;
428430
}
429431

@@ -434,13 +436,14 @@ impl<const R: usize> KeyGraph<R> {
434436
.filter(|&k| state.keys().contains_set(&self.dependencies[k]))
435437
{
436438
let weight = self.distances[state.pos(robot)][n];
439+
let n_dist = c_dist + weight;
437440
let n_state = state
438441
.with_pos(robot, n)
439-
.with_key(n, n != self.count);
440-
let n_dist = c_dist + weight;
442+
.with_key(n, n != self.count)
443+
.with_dist(n_dist);
441444

442445
if n_dist < dist.get(&n_state).copied().unwrap_or(usize::MAX) {
443-
queue.push(n_dist, n_state);
446+
queue.push(n_state);
444447
dist.insert(n_state, n_dist);
445448
}
446449
}

0 commit comments

Comments
 (0)