use std::{
collections::{HashMap, HashSet},
hash::Hash,
};
#[derive(Default)]
pub struct Clusters<T: Hash + PartialEq + Eq + Copy> {
runs: HashMap<T, u32>, clusters: HashMap<u32, HashSet<T>>, next_id: u32,
}
impl<T: Hash + PartialEq + Eq + Copy> Clusters<T> {
fn next_id(&mut self) -> u32 {
let id = self.next_id;
self.next_id += 1;
id
}
pub fn runs(&self, cluster: u32) -> &HashSet<T> {
&self.clusters[&cluster]
}
pub fn cluster(&self, run: T) -> u32 {
self.runs[&run]
}
pub fn clusters(&self) -> impl Iterator<Item = (&u32, &HashSet<T>)> {
self.clusters.iter()
}
pub fn cluster_count(&self) -> usize {
self.clusters.len()
}
pub fn insert(&mut self, run: T) -> u32 {
if let Some(&cluster) = self.runs.get(&run) {
return cluster;
}
let cluster = self.next_id();
self.runs.insert(run, cluster);
self.clusters.entry(cluster).or_default().insert(run);
cluster
}
pub fn mark_adjacency(&mut self, a: T, b: T) {
let a = self.insert(a);
let b = self.insert(b);
if a == b {
return;
}
for run in &self.clusters[&b] {
*self.runs.get_mut(run).unwrap() = a;
}
let old = self.clusters.remove(&b).unwrap();
self.clusters.get_mut(&a).unwrap().extend(old);
}
}