add hamilton path/cycle validation
This commit is contained in:
parent
2ccf946ccf
commit
dfbc6c309a
60
src/graph.rs
60
src/graph.rs
@ -116,6 +116,36 @@ where
|
||||
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> {
|
||||
self.vertices.iter()
|
||||
}
|
||||
@ -344,6 +374,36 @@ where
|
||||
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> {
|
||||
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"
|
||||
);
|
||||
|
||||
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
|
||||
println!("All tests passed.");
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user