summaryrefslogtreecommitdiffstats
path: root/src/graph.rs
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-12-23 12:18:46 -0500
committerJesse Luehrs <doy@tozt.net>2021-12-23 12:28:59 -0500
commit8d117c794835091d3c3416fc5944149372bd369c (patch)
treeb03a6076e5fb1e85676e76ec5d3a3a4cd37d08ad /src/graph.rs
parent747c6c27661f982ce0a7da06b99d35b173d3bf1a (diff)
downloadadvent-of-code-8d117c794835091d3c3416fc5944149372bd369c.tar.gz
advent-of-code-8d117c794835091d3c3416fc5944149372bd369c.zip
factor out pathfinding
Diffstat (limited to 'src/graph.rs')
-rw-r--r--src/graph.rs54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/graph.rs b/src/graph.rs
new file mode 100644
index 0000000..831cc17
--- /dev/null
+++ b/src/graph.rs
@@ -0,0 +1,54 @@
+use crate::prelude::*;
+
+pub trait Graph<Vertex, Edge>
+where
+ Vertex: std::hash::Hash + Clone + Copy + PartialEq + Eq + std::fmt::Debug,
+{
+ type Edges: IntoIterator<Item = Edge>;
+
+ fn edges(&self, v: Vertex) -> Self::Edges;
+ fn edge(&self, v: Vertex, e: Edge) -> (Vertex, i64);
+
+ fn dijkstra(&self, start: Vertex, end: Vertex) -> (i64, Vec<Vertex>) {
+ let mut to_visit = priority_queue::PriorityQueue::new();
+ let mut prev = HashMap::new();
+ prev.insert(start, start);
+ to_visit.push(start, std::cmp::Reverse(0));
+ while let Some((v, std::cmp::Reverse(distance))) = to_visit.pop() {
+ if v == end {
+ let mut path = vec![v];
+ let mut cur = v;
+ while let Some(next) = prev.get(&cur) {
+ if *next == cur {
+ break;
+ }
+ path.insert(0, *next);
+ cur = *next;
+ }
+ return (distance, path);
+ }
+
+ for e in self.edges(v) {
+ let (next, weight) = self.edge(v, e);
+ let visited = prev.contains_key(&next);
+ let new_distance = distance + weight;
+ if to_visit.get(&next).is_some() {
+ prev.insert(next, v);
+ if new_distance < to_visit.get_priority(&next).unwrap().0
+ {
+ to_visit.change_priority(
+ &next,
+ std::cmp::Reverse(new_distance),
+ );
+ }
+ } else {
+ if !visited {
+ prev.insert(next, v);
+ to_visit.push(next, std::cmp::Reverse(new_distance));
+ }
+ }
+ }
+ }
+ unreachable!()
+ }
+}