use std::hash::Hash;
use super::oxihashset_type::OxiHashSet;
use super::functions::*;
use std::collections::HashMap;
#[derive(Clone, Debug, Default)]
pub struct Bijection<A: Eq + Hash + Clone, B: Eq + Hash + Clone> {
forward: std::collections::HashMap<A, B>,
backward: std::collections::HashMap<B, A>,
}
impl<A: Eq + Hash + Clone, B: Eq + Hash + Clone> Bijection<A, B> {
pub fn new() -> Self {
Self {
forward: std::collections::HashMap::new(),
backward: std::collections::HashMap::new(),
}
}
pub fn insert(&mut self, a: A, b: B) -> bool {
if self.forward.contains_key(&a) || self.backward.contains_key(&b) {
return false;
}
self.forward.insert(a.clone(), b.clone());
self.backward.insert(b, a);
true
}
pub fn forward(&self, a: &A) -> Option<&B> {
self.forward.get(a)
}
pub fn backward(&self, b: &B) -> Option<&A> {
self.backward.get(b)
}
pub fn len(&self) -> usize {
self.forward.len()
}
pub fn is_empty(&self) -> bool {
self.forward.is_empty()
}
pub fn remove(&mut self, a: &A) -> Option<B> {
if let Some(b) = self.forward.remove(a) {
self.backward.remove(&b);
Some(b)
} else {
None
}
}
}
#[allow(dead_code)]
pub struct BloomFilterExt {
bit_array: Vec<bool>,
hash_count: usize,
expected_insertions: usize,
false_positive_rate: f64,
}
#[allow(dead_code)]
pub struct PowerSetExt<T: Eq + std::hash::Hash + Clone> {
base: OxiHashSet<T>,
cardinality_bound: usize,
}
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct MultiSet<T: Eq + Hash + Clone> {
counts: std::collections::HashMap<T, usize>,
}
impl<T: Eq + Hash + Clone> MultiSet<T> {
pub fn new() -> Self {
Self {
counts: std::collections::HashMap::new(),
}
}
pub fn insert(&mut self, elem: T) {
*self.counts.entry(elem).or_insert(0) += 1;
}
pub fn remove_one(&mut self, elem: &T) -> usize {
if let Some(c) = self.counts.get_mut(elem) {
if *c > 1 {
*c -= 1;
*c
} else {
self.counts.remove(elem);
0
}
} else {
0
}
}
pub fn count(&self, elem: &T) -> usize {
self.counts.get(elem).copied().unwrap_or(0)
}
pub fn total(&self) -> usize {
self.counts.values().sum()
}
pub fn distinct_count(&self) -> usize {
self.counts.len()
}
pub fn to_set(&self) -> OxiHashSet<T> {
OxiHashSet::from_iter(self.counts.keys().cloned())
}
pub fn is_empty(&self) -> bool {
self.counts.is_empty()
}
pub fn clear(&mut self) {
self.counts.clear();
}
pub fn contains(&self, elem: &T) -> bool {
self.counts.contains_key(elem)
}
}
#[allow(dead_code)]
pub struct SetLatticeExt<T: Eq + std::hash::Hash + Clone> {
universe: OxiHashSet<T>,
bottom: OxiHashSet<T>,
top: OxiHashSet<T>,
}
#[derive(Clone, Debug)]
pub struct UnionFind {
parent: Vec<usize>,
rank: Vec<usize>,
}
impl UnionFind {
pub fn new(n: usize) -> Self {
Self {
parent: (0..n).collect(),
rank: vec![0; n],
}
}
pub fn find(&mut self, x: usize) -> usize {
if self.parent[x] != x {
self.parent[x] = self.find(self.parent[x]);
}
self.parent[x]
}
pub fn union(&mut self, x: usize, y: usize) -> bool {
let rx = self.find(x);
let ry = self.find(y);
if rx == ry {
return false;
}
if self.rank[rx] < self.rank[ry] {
self.parent[rx] = ry;
} else if self.rank[rx] > self.rank[ry] {
self.parent[ry] = rx;
} else {
self.parent[ry] = rx;
self.rank[rx] += 1;
}
true
}
pub fn same(&mut self, x: usize, y: usize) -> bool {
self.find(x) == self.find(y)
}
pub fn component_count(&mut self) -> usize {
let n = self.parent.len();
(0..n).filter(|&i| self.find(i) == i).count()
}
pub fn component_of(&mut self, x: usize) -> Vec<usize> {
let root = self.find(x);
let n = self.parent.len();
(0..n).filter(|&i| self.find(i) == root).collect()
}
}
#[allow(dead_code)]
pub struct SetPartitionExt<T: Eq + std::hash::Hash + Clone> {
base: OxiHashSet<T>,
parts: Vec<OxiHashSet<T>>,
}
#[allow(dead_code)]
pub struct DisjointUnionExt<T: Eq + std::hash::Hash + Clone> {
left: OxiHashSet<T>,
right: OxiHashSet<T>,
total_cardinality: usize,
}