use std::{
collections::HashSet,
fmt::{Debug, Display},
};
use serde::{Deserialize, Serialize};
use crate::HgNode;
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)]
pub struct EdgeSet<N: HgNode>(pub Vec<N>);
#[allow(dead_code)]
impl<N: HgNode> EdgeSet<N> {
pub fn new() -> Self {
EdgeSet(Vec::new())
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn is_node(&self) -> bool {
self.len() == 1
}
pub fn get_first_node(&self) -> Option<N> {
self.0.first().cloned()
}
pub fn node_set(&self) -> HashSet<N> {
self.0.clone().into_iter().collect()
}
pub fn node_vec(&self) -> Vec<N> {
self.0.clone().into_iter().collect()
}
pub fn to_node_set(self) -> HashSet<N> {
self.0.into_iter().collect()
}
pub fn to_node_vec(self) -> Vec<N> {
self.0
}
pub fn add_node(&mut self, node: N) {
if let Err(ix) = self.0.binary_search(&node) {
self.0.insert(ix, node);
}
}
pub fn contains_node(&self, node: &N) -> bool {
if self.0.len() == 0 {
return false;
}
let mut ret = false;
if let Ok(ix) = self.0.binary_search(node) {
if self.0[ix] == *node {
ret = true;
}
}
ret
}
pub fn intersect_with(&mut self, rhs: &Self) {
let mut good_nodes = Vec::with_capacity(self.0.len());
for _ in 0..self.0.len() {
if let Some(node) = self.0.pop() {
if rhs.contains_node(&node) {
good_nodes.insert(0, node);
}
}
}
self.0.clear();
self.0.append(&mut good_nodes);
}
pub fn intersection(&self, rhs: &Self) -> Self {
let mut ret = Vec::new();
let l1 = self.0.len();
let l2 = rhs.0.len();
let mut left_counter = 0;
let mut right_counter = 0;
for _ix in 0..(l1 + l2) {
if left_counter == l1 || right_counter == l2 {
break;
}
if self.0[left_counter] < rhs.0[right_counter] {
left_counter += 1;
} else if self.0[left_counter] > rhs.0[right_counter] {
right_counter += 1;
} else {
ret.push(self.0[left_counter].clone());
left_counter += 1;
right_counter += 1;
}
}
EdgeSet(ret)
}
pub fn union_with(&mut self, rhs: &Self) {
for node in rhs.0.iter() {
self.add_node(*node);
}
}
pub fn union(&self, rhs: &Self) -> Self {
let mut tot = HashSet::new();
for node in self.0.iter() {
tot.insert(*node);
}
for node in rhs.0.iter() {
tot.insert(*node);
}
let mut union: Vec<N> = tot.into_iter().collect();
union.sort();
EdgeSet(union)
}
pub fn link(&self, rhs: &Self) -> Option<Self> {
if self.contains_strict(rhs) == false {
return None;
}
let mut ret_nodes = self.node_set();
for node in rhs.0.iter() {
ret_nodes.remove(node);
}
let nodes_vec: Vec<N> = ret_nodes.into_iter().collect();
Some(EdgeSet::from(nodes_vec))
}
pub fn remove_node(&mut self, node: &N) {
if let Ok(ix) = self.0.binary_search(node) {
self.0.remove(ix);
}
}
pub fn remove_nodes(&mut self, nodes: &Vec<N>) {
for node in nodes.iter() {
self.remove_node(node);
}
self.0.shrink_to_fit();
}
pub fn contains(&self, other: &Self) -> bool {
let mut self_ix = 0;
let mut other_ix = 0;
while other_ix < other.0.len() {
if self_ix == self.0.len() {
return false;
}
if self.0[self_ix] == other.0[other_ix] {
other_ix += 1;
} else {
self_ix += 1;
}
}
true
}
pub fn contains_strict(&self, other: &Self) -> bool {
self.contains(other) && self.0.len() > other.0.len()
}
}
impl<N: HgNode> Serialize for EdgeSet<N> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
if self.0.len() == 0 {
return serializer.serialize_str("[]");
}
let mut s = String::new();
s.push_str("[");
for node in self.0.iter() {
s.push_str(&format!("{:?},", node));
}
if s.ends_with(',') {
s.remove(s.len() - 1);
}
s.push_str("]");
serializer.serialize_str(&s)
}
}
impl<'de, N: HgNode> Deserialize<'de> for EdgeSet<N> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut data = <String>::deserialize(deserializer)?;
if data.starts_with("[") {
data.remove(0);
}
if data.ends_with("]") {
data.remove(data.len() - 1);
}
if data.contains(",") {
let mut v: Vec<N> = data
.split(',')
.filter_map(|x| -> Option<N> {
if let Ok(number) = x.parse() {
Some(number)
} else {
None
}
})
.collect();
v.sort();
Ok(EdgeSet(v))
} else {
if let Ok(n) = data.parse::<N>() {
Ok(EdgeSet(vec![n]))
} else {
if data.len() == 0 {
Ok(EdgeSet(vec![]))
} else {
println!("Data: {:?}", data);
panic!("Could not parse single input.");
}
}
}
}
}
impl<N: HgNode> Display for EdgeSet<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s = String::new();
s.push_str("[");
for node in self.0.iter() {
s.push_str(&format!("{:?},", node));
}
s.truncate(s.len() - 1);
s.push_str("]");
f.write_str(&s)
}
}
impl<N: HgNode, R: AsRef<[N]>> From<R> for EdgeSet<N> {
fn from(value: R) -> Self {
let ref_value = value.as_ref();
let mut nodes: Vec<N> = ref_value.iter().cloned().collect();
nodes.sort();
nodes.dedup();
EdgeSet(nodes)
}
}
#[cfg(test)]
mod test {
use super::EdgeSet;
#[test]
fn test_contains() {
let e1 = EdgeSet::from([1_u8, 2, 3, 4]);
let e2 = EdgeSet::from([1_u8, 2, 3]);
let e3 = EdgeSet::from([0_u8, 7, 9]);
let e4 = EdgeSet::from([1_u8, 2, 3, 4]);
assert!(e1.contains(&e2));
assert!(e1.contains_strict(&e2));
assert!(!e1.contains_strict(&e4));
assert!(!e2.contains(&e1));
assert!(!e1.contains(&e3));
assert!(!e3.contains(&e1));
}
#[test]
fn conversions() {
let node_vec = vec![1_u8, 2, 3];
let node_arr = [1_u8, 2, 3];
let e1 = EdgeSet::from(&node_vec);
let e2 = EdgeSet::from(&node_vec[..]);
let e3 = EdgeSet::from(node_vec);
let e4 = EdgeSet::from(node_arr.iter());
let e5 = EdgeSet::from(node_arr);
assert_eq!(e1, e2);
assert_eq!(e1, e3);
assert_eq!(e1, e4);
assert_eq!(e1, e5);
}
#[test]
fn maximal() {
let e1 = EdgeSet::from([1_u8, 2, 3]);
let e2 = EdgeSet::from([1_u8, 3]);
assert!(e1.contains_strict(&e2));
}
}