use crate::structure::graph::graph_trait::GraphWeightTrait;
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub struct Graph<W, const NODES: usize> {
pub(crate) labels: [String; NODES],
pub(crate) adjacency: [[Option<W>; NODES]; NODES],
}
impl<W: GraphWeightTrait, const NODES: usize> Graph<W, NODES> {
pub fn new() -> Self {
Self {
labels: std::array::from_fn(|n| n.to_string()),
adjacency: [[None; NODES]; NODES],
}
}
pub fn from_adjacency_matrix_with_labels(
labels: [&str; NODES],
adjacency: [[Option<W>; NODES]; NODES],
) -> Self {
Self {
labels: std::array::from_fn(|i| labels[i].to_string()),
adjacency,
}
}
pub fn from_adjacency_matrix(adjacency: [[Option<W>; NODES]; NODES]) -> Self {
Self {
labels: std::array::from_fn(|n| n.to_string()),
adjacency,
}
}
pub fn from_edges(edges: Vec<(usize, usize, W)>) -> Self {
let mut adjacency: [[Option<W>; NODES]; NODES] = [[None; NODES]; NODES];
edges
.iter()
.for_each(|edge| adjacency[edge.0][edge.1] = Some(edge.2));
Self {
labels: std::array::from_fn(|n| n.to_string()),
adjacency,
}
}
pub fn from_edges_with_labels(labels: [&str; NODES], edges: Vec<(usize, usize, W)>) -> Self {
let mut adjacency: [[Option<W>; NODES]; NODES] = [[None; NODES]; NODES];
edges
.iter()
.for_each(|edge| adjacency[edge.0][edge.1] = Some(edge.2));
Self {
labels: std::array::from_fn(|i| labels[i].to_string()),
adjacency,
}
}
}
impl<W: GraphWeightTrait, const NODES: usize> std::fmt::Display for Graph<W, NODES> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> core::fmt::Result {
let mut lengths = HashMap::<usize, usize>::new();
for j in 0..NODES {
let header_length = format!("N{}", j).len();
let max_entry_length = (0..NODES)
.map(|i| match self[(i, j)] {
None => 1,
Some(w) => w.to_string().len(),
})
.max()
.unwrap_or(1);
lengths.insert(j, header_length.max(max_entry_length));
}
write!(f, "{:>width$} ", " ", width = lengths[&0] + 1)
.expect("Failed to write to formatter");
for j in 0..NODES {
write!(f, " {:>width$}", self[j], width = lengths[&j] + 1)
.expect("Failed to write to formatter");
}
writeln!(f).expect("Failed to write to formatter");
write!(f, "{:->width$}-", "-", width = lengths[&0] + 1)
.expect("Failed to write to formatter");
for j in 0..NODES {
write!(f, "{:->width$}-", "-", width = lengths[&j] + 1)
.expect("Failed to write to formatter");
}
writeln!(f)?;
for i in 0..NODES {
write!(f, "{:>width$} |", self[i], width = lengths[&0] + 1)
.expect("Failed to write to formatter");
for j in 0..NODES {
let w = match self.adjacency[i][j] {
None => ".".to_string(),
Some(w) => w.to_string(),
};
write!(f, "{:>width$} ", w, width = lengths[&j] + 1)
.expect("Failed to write to formatter");
}
writeln!(f).expect("Failed to write to formatter");
}
Ok(())
}
}