use crate::operations::lazy_ops::PowerSet;
use crate::traits::MathSet;
use std::collections::HashSet;
use std::collections::hash_set;
use std::hash::Hash;
use std::iter::FromIterator;
#[derive(Clone)]
pub struct CustomSet<T: Eq + Hash + Clone> {
elements: HashSet<T>,
}
impl<T: Eq + Hash + Clone> CustomSet<T> {
pub fn empty() -> Self {
Self {
elements: HashSet::new(),
}
}
pub fn new<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self {
elements: HashSet::from_iter(iter),
}
}
pub fn from_predicate<I, F>(universe: I, predicate: F) -> Self
where
I: IntoIterator<Item = T>,
F: Fn(&T) -> bool,
{
Self {
elements: universe.into_iter().filter(|x| predicate(x)).collect(),
}
}
pub fn cardinality(&self) -> usize {
self.elements.len()
}
pub fn contains(&self, element: &T) -> bool {
self.elements.contains(element)
}
pub fn add(&mut self, element: T) -> bool {
self.elements.insert(element)
}
pub fn remove(&mut self, element: &T) -> bool {
self.elements.remove(element)
}
pub fn clear(&mut self) {
self.elements.clear()
}
pub fn is_subset_of(&self, other: &Self) -> bool {
self.elements.iter().all(|e| other.elements.contains(e))
}
pub fn is_proper_subset_of(&self, other: &Self) -> bool {
self.is_subset_of(other) && self.cardinality() < other.cardinality()
}
pub fn is_superset_of(&self, other: &Self) -> bool {
other.is_subset_of(self)
}
pub fn is_proper_superset_of(&self, other: &Self) -> bool {
other.is_proper_subset_of(self)
}
pub fn equals(&self, other: &Self) -> bool {
self.cardinality() == other.cardinality() && self.is_subset_of(other)
}
pub fn is_equivalent_to<U: Eq + Hash + Clone>(&self, other: &CustomSet<U>) -> bool {
self.cardinality() == other.cardinality()
}
pub fn is_disjoint_from(&self, other: &Self) -> bool {
self.elements.iter().all(|e| !other.contains(e))
}
pub fn is_empty(&self) -> bool {
self.elements.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.elements.iter()
}
pub fn intersection(&self, other: &Self) -> Self {
Self {
elements: self
.elements
.intersection(&other.elements)
.cloned()
.collect(),
}
}
pub fn union(&self, other: &Self) -> Self {
CustomSet {
elements: self.elements.union(&other.elements).cloned().collect(),
}
}
pub fn complement(&self, universal: &Self) -> Self {
Self {
elements: universal
.elements
.iter()
.filter(|e| !self.elements.contains(*e))
.cloned()
.collect(),
}
}
pub fn difference(&self, other: &Self) -> Self {
Self {
elements: self
.elements
.iter()
.filter(|e| !other.elements.contains(*e))
.cloned()
.collect(),
}
}
pub fn symmetric_difference(&self, other: &Self) -> Self {
self.union(other).difference(&self.intersection(other))
}
pub fn power_set(&self) -> PowerSet<T> {
PowerSet::new(self)
}
}
impl<T: Eq + Hash + Clone> MathSet<T> for CustomSet<T> {
fn cardinality(&self) -> usize {
self.cardinality()
}
fn contains(&self, element: &T) -> bool {
self.contains(element)
}
fn is_subset_of(&self, other: &Self) -> bool {
self.is_subset_of(other)
}
fn is_proper_subset_of(&self, other: &Self) -> bool {
self.is_proper_subset_of(other)
}
fn equals(&self, other: &Self) -> bool {
self.equals(other)
}
fn is_disjoint_from(&self, other: &Self) -> bool {
self.is_disjoint_from(other)
}
fn is_empty(&self) -> bool {
self.is_empty()
}
}
impl<T: Eq + Hash + Clone> FromIterator<T> for CustomSet<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
CustomSet::new(iter)
}
}
impl<T: Eq + Hash + Clone> IntoIterator for CustomSet<T> {
type Item = T;
type IntoIter = hash_set::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.elements.into_iter()
}
}
impl<T: Eq + Hash + Clone> From<Vec<T>> for CustomSet<T> {
fn from(vec: Vec<T>) -> Self {
CustomSet::new(vec)
}
}
impl<T: Eq + Hash + Clone> From<&[T]> for CustomSet<T> {
fn from(slice: &[T]) -> Self {
CustomSet::new(slice.iter().cloned())
}
}
impl<T: Eq + Hash + Clone + std::fmt::Display> std::fmt::Display for CustomSet<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.is_empty() {
write!(f, "∅")
} else {
let elements: Vec<_> = self.elements.iter().collect();
write!(
f,
"{{{}}}",
elements
.iter()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join(", ")
)
}
}
}
impl<T: Eq + Hash + Clone + std::fmt::Debug> std::fmt::Debug for CustomSet<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "CustomSet({:?})", self.elements)
}
}
impl<T: Eq + Hash + Clone> PartialEq for CustomSet<T> {
fn eq(&self, other: &Self) -> bool {
self.equals(other)
}
}
impl<T: Eq + Hash + Clone> Eq for CustomSet<T> {}
impl<T: Eq + Hash + Clone + std::fmt::Debug> std::hash::Hash for CustomSet<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let mut elements: Vec<_> = self.elements.iter().collect();
elements.sort_by(|a, b| format!("{:?}", a).cmp(&format!("{:?}", b)));
for element in elements {
element.hash(state);
}
}
}