Compare commits
2 Commits
26ff260ac8
...
dfbc6c309a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfbc6c309a | ||
|
|
2ccf946ccf |
64
src/graph.rs
64
src/graph.rs
@ -116,6 +116,36 @@ where
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// check if a provided path is a hamilton path within the graph,
|
||||||
|
/// meaning it contains all of the graphs vertices exactly once.
|
||||||
|
///
|
||||||
|
/// an empty path is considered hamiltonian for empty graphs.
|
||||||
|
pub fn is_hamilton_path(&self, path: &[V]) -> bool {
|
||||||
|
match self.vertex_count() {
|
||||||
|
0 => path.is_empty(),
|
||||||
|
n => {
|
||||||
|
let edges_exist = path.windows(2).all(|w| self.has_edge((&w[0], &w[1])));
|
||||||
|
let has_all_verts_once =
|
||||||
|
path.len() == n && self.vertices == path.iter().cloned().collect();
|
||||||
|
|
||||||
|
edges_exist && has_all_verts_once
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// check if a provided path is a hamilton cycle within the graph,
|
||||||
|
/// meaning it is a cycle and contains all of the graphs vertices exactly once.
|
||||||
|
///
|
||||||
|
/// this assumes a path only containing the start/end vertex once,
|
||||||
|
/// so a valid 2-vertex-loop would be represented as `[v, w]` and not `[v, w, v]`.
|
||||||
|
///
|
||||||
|
/// empty paths are never considered a cycle.
|
||||||
|
pub fn is_hamilton_cycle(&self, path: &[V]) -> bool {
|
||||||
|
!path.is_empty()
|
||||||
|
&& self.is_hamilton_path(path)
|
||||||
|
&& self.has_edge((path.last().unwrap(), path.first().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &V> {
|
pub fn iter(&self) -> impl Iterator<Item = &V> {
|
||||||
self.vertices.iter()
|
self.vertices.iter()
|
||||||
}
|
}
|
||||||
@ -290,6 +320,10 @@ where
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// find a path between two nodes using dijkstras algorithm.
|
||||||
|
///
|
||||||
|
/// this take into account edge weights and finds a path with
|
||||||
|
/// the least total weight.
|
||||||
pub fn find_path_dijkstra(&self, from: &V, to: &V) -> Option<Vec<V>> {
|
pub fn find_path_dijkstra(&self, from: &V, to: &V) -> Option<Vec<V>> {
|
||||||
use std::cmp::Reverse as Rev;
|
use std::cmp::Reverse as Rev;
|
||||||
use std::collections::BinaryHeap;
|
use std::collections::BinaryHeap;
|
||||||
@ -340,6 +374,36 @@ where
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// check if a provided path is a hamilton path within the graph,
|
||||||
|
/// meaning it contains all of the graphs vertices exactly once.
|
||||||
|
///
|
||||||
|
/// an empty path is considered hamiltonian for empty graphs.
|
||||||
|
pub fn is_hamilton_path(&self, path: &[V]) -> bool {
|
||||||
|
match self.vertex_count() {
|
||||||
|
0 => path.is_empty(),
|
||||||
|
n => {
|
||||||
|
let edges_exist = path.windows(2).all(|w| self.has_edge((&w[0], &w[1])));
|
||||||
|
let has_all_verts_once =
|
||||||
|
path.len() == n && self.vertices == path.iter().cloned().collect();
|
||||||
|
|
||||||
|
edges_exist && has_all_verts_once
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// check if a provided path is a hamilton cycle within the graph,
|
||||||
|
/// meaning it is a cycle and contains all of the graphs vertices exactly once.
|
||||||
|
///
|
||||||
|
/// this assumes a path only containing the start/end vertex once,
|
||||||
|
/// so a valid 2-vertex-loop would be represented as `[v, w]` and not `[v, w, v]`.
|
||||||
|
///
|
||||||
|
/// empty paths are never considered a cycle.
|
||||||
|
pub fn is_hamilton_cycle(&self, path: &[V]) -> bool {
|
||||||
|
!path.is_empty()
|
||||||
|
&& self.is_hamilton_path(path)
|
||||||
|
&& self.has_edge((path.last().unwrap(), path.first().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &V> {
|
pub fn iter(&self) -> impl Iterator<Item = &V> {
|
||||||
self.vertices.iter()
|
self.vertices.iter()
|
||||||
}
|
}
|
||||||
|
|||||||
60
src/main.rs
60
src/main.rs
@ -104,6 +104,66 @@ fn main() {
|
|||||||
"Dijkstra should find cheapest way in weighted example graph"
|
"Dijkstra should find cheapest way in weighted example graph"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let path = ['a', 'b', 'c', 'd', 'e', 'f'];
|
||||||
|
assert!(
|
||||||
|
g.is_hamilton_path(&path),
|
||||||
|
"Valid hamilton path in graph should be recognized as such"
|
||||||
|
);
|
||||||
|
|
||||||
|
let path = ['a', 'd', 'c', 'b', 'e', 'f'];
|
||||||
|
assert!(
|
||||||
|
!g.is_hamilton_path(&path),
|
||||||
|
"A path with a non-existent edge is not hamiltonian"
|
||||||
|
);
|
||||||
|
|
||||||
|
let path = ['a', 'b', 'c', 'd', 'e'];
|
||||||
|
assert!(
|
||||||
|
!g.is_hamilton_path(&path),
|
||||||
|
"A path with missing vertices is not hamiltonian"
|
||||||
|
);
|
||||||
|
|
||||||
|
let path = ['f', 'e', 'd', 'c', 'b', 'a', 'b'];
|
||||||
|
assert!(
|
||||||
|
!g.is_hamilton_path(&path),
|
||||||
|
"A path with duplicate vertices is not hamiltonian"
|
||||||
|
);
|
||||||
|
|
||||||
|
// test graph:
|
||||||
|
// ┏━━━━━1━━━━━┓
|
||||||
|
// -> 0 ┃ 3
|
||||||
|
// ┗━━━━━2━━━━━┛
|
||||||
|
|
||||||
|
let g = graph! {
|
||||||
|
0: 1, 2;
|
||||||
|
1: 0, 2, 3;
|
||||||
|
2: 0, 1, 3;
|
||||||
|
3: 1, 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
let path = [0, 1, 3, 2];
|
||||||
|
assert!(
|
||||||
|
g.is_hamilton_cycle(&path),
|
||||||
|
"Valid hamilton cycle in graph should be recognized as such"
|
||||||
|
);
|
||||||
|
|
||||||
|
let path = [0, 3, 1, 2];
|
||||||
|
assert!(
|
||||||
|
!g.is_hamilton_cycle(&path),
|
||||||
|
"A path with a non-existent edge is not a hamilton cycle"
|
||||||
|
);
|
||||||
|
|
||||||
|
let path = [0, 1, 2, 3];
|
||||||
|
assert!(
|
||||||
|
!g.is_hamilton_cycle(&path),
|
||||||
|
"Hamilton path that does not loop is not a hamilton cycle"
|
||||||
|
);
|
||||||
|
|
||||||
|
let path = [0, 1, 2];
|
||||||
|
assert!(
|
||||||
|
!g.is_hamilton_cycle(&path),
|
||||||
|
"Cycle that does not contain all vertices is not a hamilton cycle"
|
||||||
|
);
|
||||||
|
|
||||||
// yay
|
// yay
|
||||||
println!("All tests passed.");
|
println!("All tests passed.");
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user