heh
Diffstat (limited to 'src/util.rs')
| -rw-r--r-- | src/util.rs | 87 |
1 files changed, 78 insertions, 9 deletions
diff --git a/src/util.rs b/src/util.rs index 9613bf1..0afefa4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -42,10 +42,11 @@ pub mod prelude { collections::{VecDeque, hash_map::Entry}, fmt::{Debug, Display}, hint::black_box as boxd, + intrinsics::transmute_unchecked as transmute, io::{self, Read, Write}, iter, iter::{chain, once, repeat_n, successors, zip}, - mem::{replace as rplc, swap, transmute as rint}, + mem::{replace as rplc, swap}, ops::Range, }; } @@ -504,26 +505,64 @@ pub fn dijkstra_h<N: Debug + Eq + Hash + Copy + Ord, I: Iterator<Item = (N, u16) } dang!() } +#[derive(Debug, Clone, Copy)] +pub struct Left<T, U>(T, U); -pub fn steps<N: Debug + Eq + Hash + Clone + Ord, I: Iterator<Item = N>>( +impl<T: Hash, U> Hash for Left<T, U> { + fn hash<H: std::hash::Hasher>(&self, state: &mut H) { + self.0.hash(state); + } +} + +impl<T: PartialEq, U> PartialEq for Left<T, U> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} +impl<T: Eq, U> Eq for Left<T, U> {} +impl<T: PartialOrd, U> PartialOrd for Left<T, U> { + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + self.0.partial_cmp(&other.0) + } +} +impl<T: Ord, U> Ord for Left<T, U> { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0.cmp(&other.0) + } +} +pub fn steps<N: Debug + Eq + Hash + Clone, I: Iterator<Item = N>>( start: N, graph: impl Fn(N) -> I, end: impl Fn(&N) -> bool, -) -> Option<(N, usize)> { +) -> Option<Left<N, usize>> { bfs( - (start, 0usize), - |(n, steps)| graph(n).map(move |x| (x, steps + 1)), + Left(start, 0usize), + |Left(n, steps)| graph(n).map(move |x| Left(x, steps + 1)), |x| end(&x.0), ) } +pub fn steps_astar<N: Debug + Eq + Hash + Clone, I: Iterator<Item = (N, i16)>>( + start: N, + graph: impl Fn(N) -> I, + heuristic: impl Fn(&N) -> i16, + goal: impl Fn(&N) -> bool, +) -> Option<(i16, Left<N, usize>)> { + astar( + Left(start, 0usize), + |Left(n, steps)| graph(n).map(move |(x, cost)| (Left(x, steps + 1), cost)), + |x| heuristic(&x.0), + |x| goal(&x.0), + ) +} + pub fn bfs<N: Debug + Eq + Hash + Clone, I: Iterator<Item = N>>( start: N, graph: impl Fn(N) -> I, end: impl Fn(&N) -> bool, ) -> Option<N> { let mut q = VecDeque::with_capacity(1024); - let mut s = HashSet::default(); + let mut s = HashSet::with_capacity_and_hasher(1024, rustc_hash::FxBuildHasher::default()); q.push_back(start); while let Some(n) = q.pop_front() { if end(&n) { @@ -539,6 +578,36 @@ pub fn bfs<N: Debug + Eq + Hash + Clone, I: Iterator<Item = N>>( // print!("{n:?} "); q.push_back(n); } + if s.len() % (1 << 20) == 0 { + dbg!(s.len()); + } + } + None +} + +pub fn astar<N: Debug + Eq + Hash + Clone, I: Iterator<Item = (N, i16)>>( + start: N, + graph: impl Fn(N) -> I, + heuristic: impl Fn(&N) -> i16, + goal: impl Fn(&N) -> bool, +) -> Option<(i16, N)> { + let mut q = BinaryHeap::with_capacity(1024); + let mut score = HashMap::default(); + score.insert(start.clone(), 0); + q.push(Reverse(Left(heuristic(&start), start))); + while let Some(Reverse(Left(c, n))) = q.pop() { + if goal(&n) { + return Some((c, n)); + } + for (n_, d) in graph(n.clone()) { + let g = score[&n] + d; + let of = score.get(&n_).unwrap_or(&i16::MAX); + if g < *of { + score.insert(n_.clone(), g); + let f = g + heuristic(&n_); + q.push(Reverse(Left(f, n_))); + } + } } None } @@ -550,8 +619,8 @@ pub fn dijkstra<N: Debug + Eq + Hash + Clone + Ord, I: Iterator<Item = (N, u16)> ) -> Option<(u16, N)> { let mut q = BinaryHeap::new(); let mut s = HashSet::default(); - q.push(Reverse((0, start))); - while let Some(Reverse((c, n))) = q.pop() { + q.push(Reverse(Left(0, start))); + while let Some(Reverse(Left(c, n))) = q.pop() { if end(&n) { return Some((c, n)); } @@ -563,7 +632,7 @@ pub fn dijkstra<N: Debug + Eq + Hash + Clone + Ord, I: Iterator<Item = (N, u16)> continue; } // print!("{n:?} "); - q.push(Reverse((c + d, n))); + q.push(Reverse(Left(c + d, n))); } } None |