From 14a3342f60e5c2b631e7fe1b9007961a4b77d606 Mon Sep 17 00:00:00 2001 From: mxhagen Date: Sun, 16 Feb 2025 19:25:00 +0100 Subject: [PATCH] add graph! macro and vertex/edge_count --- src/graph.rs | 34 +++++++++++++++++++++++++++++----- src/main.rs | 42 +++++++++++++++++++++--------------------- 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/graph.rs b/src/graph.rs index a43e081..6a6407d 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -4,7 +4,7 @@ use std::{ }; pub struct Graph { - pub vertices: Vec, + pub vertices: HashSet, pub edges: HashMap>, } @@ -12,6 +12,16 @@ impl Graph where V: Eq + Hash + Ord + Clone, { + /// get the number of vertices of the graph + pub fn vertex_count(&self) -> usize { + self.vertices.len() + } + + /// get the number of edges of the graph + pub fn edge_count(&self) -> usize { + self.edges.values().map(Vec::len).sum() + } + /// check if an edge is contained in the graph /// (only checks the provided direction) pub fn has_edge(&self, edge: (&V, &V)) -> bool { @@ -49,8 +59,7 @@ where q.push_back(vec![from]); visited.insert(from); - while !q.is_empty() { - let mut path = q.pop_front().unwrap(); + while let Some(mut path) = q.pop_front() { let current = path.last().unwrap(); for neighbor in self.neighbors(current) { @@ -81,8 +90,7 @@ where q.push(vec![from]); - while !q.is_empty() { - let mut path = q.pop().unwrap(); + while let Some(mut path) = q.pop() { let ¤t = path.last().unwrap(); if current == to { @@ -103,3 +111,19 @@ where None } } + +#[macro_export] +macro_rules! graph { + ( $( $v:tt : $( $e:tt ),* );* $(;)? ) => {{ + let mut edges = std::collections::HashMap::new(); + let mut vertices = std::collections::HashSet::new(); + + $( + vertices.insert($v); + edges.insert($v, vec![$( $e ),*]); + $( vertices.insert($e); )* + )* + + Graph { vertices, edges } + }}; +} diff --git a/src/main.rs b/src/main.rs index 47e65a9..d2f4d9d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - mod graph; pub use graph::Graph; @@ -9,24 +7,18 @@ fn main() { // -> 0 ┃ 3 // ┗━━━━━2━━━━━┛ - let vs = vec![0, 1, 2, 3]; - let es = HashMap::from([ - (0, vec![1, 2]), - (1, vec![0, 2, 3]), - (2, vec![0, 1, 3]), - (3, vec![1, 2]), - ]); - - let g = Graph { - vertices: vs.clone(), - edges: es.clone(), + let g = graph! { + 0: 1, 2; + 1: 0, 2, 3; + 2: 0, 1, 3; + 3: 1, 2; }; - for v in &vs { + for v in &g.vertices { assert!(g.has_vertex(v), "G should contain vertex {v}"); } - for (a, neighbors) in &es { + for (a, neighbors) in &g.edges { for b in neighbors { assert!(g.has_edge((a, b)), "G should contain edge ({a}, {b})"); assert!( @@ -36,19 +28,27 @@ fn main() { } } - for i in 0..vs.len() { - for j in i + 1..vs.len() { + let n = g.vertex_count(); + let vs = g.vertices.iter().collect::>(); + for i in 0..n { + for j in i + 1..n { let (a, b) = (vs[i], vs[j]); let shortest_path_length = match (a, b) { (0, 3) | (3, 0) => 3, _ => 2, }; - let path = g.find_path_dfs(&a, &b); - assert!(path.is_some(), "Path from {a} to {b} should be found in G with dfs"); + let path = g.find_path_dfs(a, b); + assert!( + path.is_some(), + "Path from {a} to {b} should be found in G with dfs" + ); - let path = g.find_path_bfs(&a, &b); - assert!(path.is_some(), "Path from {a} to {b} should be found in G with bfs"); + let path = g.find_path_bfs(a, b); + assert!( + path.is_some(), + "Path from {a} to {b} should be found in G with bfs" + ); let path = path.unwrap(); assert_eq!(