diff options
author | Jesse Luehrs <doy@tozt.net> | 2021-12-23 12:18:46 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2021-12-23 12:28:59 -0500 |
commit | 8d117c794835091d3c3416fc5944149372bd369c (patch) | |
tree | b03a6076e5fb1e85676e76ec5d3a3a4cd37d08ad /src/graph.rs | |
parent | 747c6c27661f982ce0a7da06b99d35b173d3bf1a (diff) | |
download | advent-of-code-8d117c794835091d3c3416fc5944149372bd369c.tar.gz advent-of-code-8d117c794835091d3c3416fc5944149372bd369c.zip |
factor out pathfinding
Diffstat (limited to 'src/graph.rs')
-rw-r--r-- | src/graph.rs | 54 |
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!() + } +} |