use std::collections::BTreeSet;
pub trait Semigroup: Sized {
fn combine(self, other: Self) -> Self;
fn combine_all<I: IntoIterator<Item = Self>>(iter: I) -> Option<Self> {
iter.into_iter().reduce(|a, b| a.combine(b))
}
}
impl<T: Ord + Clone> Semigroup for BTreeSet<T> {
#[inline]
fn combine(self, other: Self) -> Self {
self.union(&other).cloned().collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_btreeset_semigroup_associativity() {
let a: BTreeSet<i32> = [1, 2].iter().cloned().collect();
let b: BTreeSet<i32> = [2, 3].iter().cloned().collect();
let c: BTreeSet<i32> = [3, 4].iter().cloned().collect();
let left = a.clone().combine(b.clone()).combine(c.clone());
let right = a.combine(b.combine(c));
assert_eq!(left, right);
}
#[test]
fn test_combine_all() {
let sets = vec![
[1, 2].iter().cloned().collect::<BTreeSet<_>>(),
[3, 4].iter().cloned().collect::<BTreeSet<_>>(),
[5].iter().cloned().collect::<BTreeSet<_>>(),
];
let combined = BTreeSet::combine_all(sets).unwrap();
assert_eq!(combined, [1, 2, 3, 4, 5].iter().cloned().collect());
}
#[test]
fn test_combine_all_empty() {
let empty: Vec<BTreeSet<i32>> = vec![];
assert_eq!(BTreeSet::combine_all(empty), None);
}
}