use core::{cmp::Ordering, fmt, iter::FusedIterator};
use crate::{
comparator::{Comparator, OrdComparator},
level_generator::LevelGenerator,
ordered_skip_list::Iter,
skip_set::SkipSet,
};
type PeekIter<'a, T, const N: usize> = core::iter::Peekable<Iter<'a, T, N>>;
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Difference<'a, T, const N: usize = 16, C: Comparator<T> = OrdComparator> {
self_iter: PeekIter<'a, T, N>,
other_iter: PeekIter<'a, T, N>,
comparator: &'a C,
}
impl<T: fmt::Debug, const N: usize, C: Comparator<T>> fmt::Debug for Difference<'_, T, N, C> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(Difference {
self_iter: self.self_iter.clone(),
other_iter: self.other_iter.clone(),
comparator: self.comparator,
})
.finish()
}
}
impl<'a, T, const N: usize, C: Comparator<T>> Iterator for Difference<'a, T, N, C> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
let ord = match (self.self_iter.peek(), self.other_iter.peek()) {
(None, _) => return None,
(Some(_), None) => Ordering::Less,
(Some(a), Some(b)) => self.comparator.compare(*a, *b),
};
match ord {
Ordering::Less => return self.self_iter.next(),
Ordering::Equal => {
self.self_iter.next();
self.other_iter.next();
}
Ordering::Greater => {
self.other_iter.next();
}
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.self_iter.size_hint().1)
}
}
impl<T, const N: usize, C: Comparator<T>> FusedIterator for Difference<'_, T, N, C> {}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Intersection<'a, T, const N: usize = 16, C: Comparator<T> = OrdComparator> {
self_iter: PeekIter<'a, T, N>,
other_iter: PeekIter<'a, T, N>,
comparator: &'a C,
}
impl<T: fmt::Debug, const N: usize, C: Comparator<T>> fmt::Debug for Intersection<'_, T, N, C> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(Intersection {
self_iter: self.self_iter.clone(),
other_iter: self.other_iter.clone(),
comparator: self.comparator,
})
.finish()
}
}
impl<'a, T, const N: usize, C: Comparator<T>> Iterator for Intersection<'a, T, N, C> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
let ord = match (self.self_iter.peek(), self.other_iter.peek()) {
(None, _) | (_, None) => return None,
(Some(a), Some(b)) => self.comparator.compare(*a, *b),
};
match ord {
Ordering::Equal => {
self.other_iter.next();
return self.self_iter.next();
}
Ordering::Less => {
self.self_iter.next();
}
Ordering::Greater => {
self.other_iter.next();
}
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let a = self.self_iter.size_hint().1;
let b = self.other_iter.size_hint().1;
let upper = match (a, b) {
(Some(x), Some(y)) => Some(x.min(y)),
(Some(x), None) | (None, Some(x)) => Some(x),
(None, None) => None,
};
(0, upper)
}
}
impl<T, const N: usize, C: Comparator<T>> FusedIterator for Intersection<'_, T, N, C> {}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct SymmetricDifference<'a, T, const N: usize = 16, C: Comparator<T> = OrdComparator> {
self_iter: PeekIter<'a, T, N>,
other_iter: PeekIter<'a, T, N>,
comparator: &'a C,
}
impl<T: fmt::Debug, const N: usize, C: Comparator<T>> fmt::Debug
for SymmetricDifference<'_, T, N, C>
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(SymmetricDifference {
self_iter: self.self_iter.clone(),
other_iter: self.other_iter.clone(),
comparator: self.comparator,
})
.finish()
}
}
impl<'a, T, const N: usize, C: Comparator<T>> Iterator for SymmetricDifference<'a, T, N, C> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
let ord = match (self.self_iter.peek(), self.other_iter.peek()) {
(None, _) => return self.other_iter.next(),
(Some(_), None) => return self.self_iter.next(),
(Some(a), Some(b)) => self.comparator.compare(*a, *b),
};
match ord {
Ordering::Less => return self.self_iter.next(),
Ordering::Greater => return self.other_iter.next(),
Ordering::Equal => {
self.self_iter.next();
self.other_iter.next();
}
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let a = self.self_iter.size_hint().1;
let b = self.other_iter.size_hint().1;
let upper = match (a, b) {
(Some(x), Some(y)) => Some(x.saturating_add(y)),
_ => None,
};
(0, upper)
}
}
impl<T, const N: usize, C: Comparator<T>> FusedIterator for SymmetricDifference<'_, T, N, C> {}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Union<'a, T, const N: usize = 16, C: Comparator<T> = OrdComparator> {
self_iter: PeekIter<'a, T, N>,
other_iter: PeekIter<'a, T, N>,
comparator: &'a C,
}
impl<T: fmt::Debug, const N: usize, C: Comparator<T>> fmt::Debug for Union<'_, T, N, C> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(Union {
self_iter: self.self_iter.clone(),
other_iter: self.other_iter.clone(),
comparator: self.comparator,
})
.finish()
}
}
impl<'a, T, const N: usize, C: Comparator<T>> Iterator for Union<'a, T, N, C> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let ord = match (self.self_iter.peek(), self.other_iter.peek()) {
(None, _) => return self.other_iter.next(),
(Some(_), None) => return self.self_iter.next(),
(Some(a), Some(b)) => self.comparator.compare(*a, *b),
};
match ord {
Ordering::Less => self.self_iter.next(),
Ordering::Greater => self.other_iter.next(),
Ordering::Equal => {
self.other_iter.next();
self.self_iter.next()
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let a = self.self_iter.size_hint().1;
let b = self.other_iter.size_hint().1;
let upper = match (a, b) {
(Some(x), Some(y)) => Some(x.saturating_add(y)),
_ => None,
};
(0, upper)
}
}
impl<T, const N: usize, C: Comparator<T>> FusedIterator for Union<'_, T, N, C> {}
impl<T, C: Comparator<T>, G: LevelGenerator, const N: usize> SkipSet<T, N, C, G> {
#[inline]
#[must_use]
pub fn is_disjoint(&self, other: &Self) -> bool {
let mut ai = self.inner.iter().peekable();
let mut bi = other.inner.iter().peekable();
loop {
let ord = match (ai.peek(), bi.peek()) {
(None, _) | (_, None) => return true,
(Some(a), Some(b)) => self.inner.comparator().compare(*a, *b),
};
match ord {
Ordering::Equal => return false,
Ordering::Less => {
ai.next();
}
Ordering::Greater => {
bi.next();
}
}
}
}
#[inline]
#[must_use]
pub fn is_subset(&self, other: &Self) -> bool {
if self.len() > other.len() {
return false;
}
let mut ai = self.inner.iter().peekable();
let mut bi = other.inner.iter().peekable();
loop {
let ord = match (ai.peek(), bi.peek()) {
(None, _) => return true,
(Some(_), None) => return false,
(Some(a), Some(b)) => self.inner.comparator().compare(*a, *b),
};
match ord {
Ordering::Equal => {
ai.next();
bi.next();
}
Ordering::Less => return false,
Ordering::Greater => {
bi.next();
}
}
}
}
#[inline]
#[must_use]
pub fn is_superset(&self, other: &Self) -> bool {
other.is_subset(self)
}
#[inline]
pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, T, N, C> {
Difference {
self_iter: self.inner.iter().peekable(),
other_iter: other.inner.iter().peekable(),
comparator: self.inner.comparator(),
}
}
#[inline]
pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T, N, C> {
Intersection {
self_iter: self.inner.iter().peekable(),
other_iter: other.inner.iter().peekable(),
comparator: self.inner.comparator(),
}
}
#[inline]
pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, T, N, C> {
SymmetricDifference {
self_iter: self.inner.iter().peekable(),
other_iter: other.inner.iter().peekable(),
comparator: self.inner.comparator(),
}
}
#[inline]
pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T, N, C> {
Union {
self_iter: self.inner.iter().peekable(),
other_iter: other.inner.iter().peekable(),
comparator: self.inner.comparator(),
}
}
}
#[cfg(test)]
mod tests {
use core::cmp::Ordering;
use pretty_assertions::assert_eq;
use super::SkipSet;
use crate::comparator::FnComparator;
#[expect(
clippy::trivially_copy_pass_by_ref,
reason = "matches Comparator<T> signature"
)]
fn rev_cmp(x: &i32, y: &i32) -> Ordering {
y.cmp(x)
}
type RevSet = SkipSet<i32, 16, FnComparator<fn(&i32, &i32) -> Ordering>>;
fn make_rev_set(values: &[i32]) -> RevSet {
let fnptr: fn(&i32, &i32) -> Ordering = rev_cmp;
let mut set = SkipSet::with_comparator(FnComparator(fnptr));
for &v in values {
set.insert(v);
}
set
}
fn make_set(values: &[i32]) -> SkipSet<i32> {
let mut set = SkipSet::new();
for &v in values {
set.insert(v);
}
set
}
fn collect_diff(a: &SkipSet<i32>, b: &SkipSet<i32>) -> Vec<i32> {
a.difference(b).copied().collect()
}
fn collect_inter(a: &SkipSet<i32>, b: &SkipSet<i32>) -> Vec<i32> {
a.intersection(b).copied().collect()
}
fn collect_sym(a: &SkipSet<i32>, b: &SkipSet<i32>) -> Vec<i32> {
a.symmetric_difference(b).copied().collect()
}
fn collect_union(a: &SkipSet<i32>, b: &SkipSet<i32>) -> Vec<i32> {
a.union(b).copied().collect()
}
#[test]
fn is_disjoint_both_empty() {
let a = make_set(&[]);
let b = make_set(&[]);
assert!(a.is_disjoint(&b));
}
#[test]
fn is_disjoint_self_empty() {
let a = make_set(&[]);
let b = make_set(&[1, 2, 3]);
assert!(a.is_disjoint(&b));
}
#[test]
fn is_disjoint_other_empty() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[]);
assert!(a.is_disjoint(&b));
}
#[test]
fn is_disjoint_no_overlap() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[4, 5, 6]);
assert!(a.is_disjoint(&b));
}
#[test]
fn is_disjoint_partial_overlap() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[3, 4, 5]);
assert!(!a.is_disjoint(&b));
}
#[test]
fn is_disjoint_identical_sets() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[1, 2, 3]);
assert!(!a.is_disjoint(&b));
}
#[test]
fn is_disjoint_single_shared_element() {
let a = make_set(&[1, 2, 5]);
let b = make_set(&[3, 4, 5]);
assert!(!a.is_disjoint(&b));
}
#[test]
fn is_disjoint_custom_comparator() {
let a = make_rev_set(&[3, 1]);
let mut b = make_rev_set(&[4, 2]);
assert!(a.is_disjoint(&b));
b.insert(1);
assert!(!a.is_disjoint(&b));
}
#[test]
fn is_subset_both_empty() {
let a = make_set(&[]);
let b = make_set(&[]);
assert!(a.is_subset(&b));
}
#[test]
fn is_subset_empty_is_subset_of_nonempty() {
let a = make_set(&[]);
let b = make_set(&[1, 2]);
assert!(a.is_subset(&b));
}
#[test]
fn is_subset_nonempty_is_not_subset_of_empty() {
let a = make_set(&[1]);
let b = make_set(&[]);
assert!(!a.is_subset(&b));
}
#[test]
fn is_subset_proper_subset() {
let a = make_set(&[1, 2]);
let b = make_set(&[1, 2, 3]);
assert!(a.is_subset(&b));
}
#[test]
fn is_subset_equal_sets() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[1, 2, 3]);
assert!(a.is_subset(&b));
}
#[test]
fn is_subset_not_subset_due_to_missing_element() {
let a = make_set(&[1, 2, 4]);
let b = make_set(&[1, 2, 3]);
assert!(!a.is_subset(&b));
}
#[test]
fn is_subset_not_subset_larger() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[1, 2]);
assert!(!a.is_subset(&b));
}
#[test]
fn is_subset_disjoint_not_subset() {
let a = make_set(&[1, 2]);
let b = make_set(&[3, 4]);
assert!(!a.is_subset(&b));
}
#[test]
fn is_superset_basic() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[1, 2]);
assert!(a.is_superset(&b));
assert!(!b.is_superset(&a));
}
#[test]
fn is_superset_equal_sets() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[1, 2, 3]);
assert!(a.is_superset(&b));
assert!(b.is_superset(&a));
}
#[test]
fn is_superset_empty_is_superset_of_empty() {
let a = make_set(&[]);
let b = make_set(&[]);
assert!(a.is_superset(&b));
}
#[test]
fn difference_both_empty() {
let a = make_set(&[]);
let b = make_set(&[]);
assert_eq!(collect_diff(&a, &b), Vec::<i32>::new());
}
#[test]
fn difference_self_empty() {
let a = make_set(&[]);
let b = make_set(&[1, 2, 3]);
assert_eq!(collect_diff(&a, &b), Vec::<i32>::new());
}
#[test]
fn difference_other_empty() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[]);
assert_eq!(collect_diff(&a, &b), vec![1, 2, 3]);
}
#[test]
fn difference_disjoint() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[4, 5, 6]);
assert_eq!(collect_diff(&a, &b), vec![1, 2, 3]);
}
#[test]
fn difference_identical() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[1, 2, 3]);
assert_eq!(collect_diff(&a, &b), Vec::<i32>::new());
}
#[test]
fn difference_partial_overlap() {
let a = make_set(&[1, 2, 3, 4]);
let b = make_set(&[2, 4]);
assert_eq!(collect_diff(&a, &b), vec![1, 3]);
}
#[test]
fn difference_all_in_other() {
let a = make_set(&[1, 2]);
let b = make_set(&[1, 2, 3, 4]);
assert_eq!(collect_diff(&a, &b), Vec::<i32>::new());
}
#[test]
fn difference_other_is_subset() {
let a = make_set(&[1, 2, 3, 4, 5]);
let b = make_set(&[2, 4]);
assert_eq!(collect_diff(&a, &b), vec![1, 3, 5]);
}
#[test]
fn difference_custom_comparator() {
let a = make_rev_set(&[1, 2, 3]);
let b = make_rev_set(&[2]);
let diff: Vec<i32> = a.difference(&b).copied().collect();
assert_eq!(diff, vec![3, 1]);
}
#[test]
fn difference_size_hint() {
let a = make_set(&[1, 2, 3, 4]);
let b = make_set(&[2, 4]);
let iter = a.difference(&b);
let (lo, hi) = iter.size_hint();
assert_eq!(lo, 0);
assert!(hi.is_some_and(|h| h >= 2)); }
#[test]
fn intersection_both_empty() {
let a = make_set(&[]);
let b = make_set(&[]);
assert_eq!(collect_inter(&a, &b), Vec::<i32>::new());
}
#[test]
fn intersection_self_empty() {
let a = make_set(&[]);
let b = make_set(&[1, 2, 3]);
assert_eq!(collect_inter(&a, &b), Vec::<i32>::new());
}
#[test]
fn intersection_other_empty() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[]);
assert_eq!(collect_inter(&a, &b), Vec::<i32>::new());
}
#[test]
fn intersection_disjoint() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[4, 5, 6]);
assert_eq!(collect_inter(&a, &b), Vec::<i32>::new());
}
#[test]
fn intersection_identical() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[1, 2, 3]);
assert_eq!(collect_inter(&a, &b), vec![1, 2, 3]);
}
#[test]
fn intersection_partial_overlap() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[2, 3, 4]);
assert_eq!(collect_inter(&a, &b), vec![2, 3]);
}
#[test]
fn intersection_one_is_subset() {
let a = make_set(&[1, 2]);
let b = make_set(&[1, 2, 3, 4]);
assert_eq!(collect_inter(&a, &b), vec![1, 2]);
}
#[test]
fn intersection_custom_comparator() {
let a = make_rev_set(&[1, 2, 3]);
let b = make_rev_set(&[1, 3]);
let inter: Vec<i32> = a.intersection(&b).copied().collect();
assert_eq!(inter, vec![3, 1]); }
#[test]
fn symmetric_difference_both_empty() {
let a = make_set(&[]);
let b = make_set(&[]);
assert_eq!(collect_sym(&a, &b), Vec::<i32>::new());
}
#[test]
fn symmetric_difference_self_empty() {
let a = make_set(&[]);
let b = make_set(&[1, 2, 3]);
assert_eq!(collect_sym(&a, &b), vec![1, 2, 3]);
}
#[test]
fn symmetric_difference_other_empty() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[]);
assert_eq!(collect_sym(&a, &b), vec![1, 2, 3]);
}
#[test]
fn symmetric_difference_disjoint() {
let a = make_set(&[1, 3, 5]);
let b = make_set(&[2, 4, 6]);
assert_eq!(collect_sym(&a, &b), vec![1, 2, 3, 4, 5, 6]);
}
#[test]
fn symmetric_difference_identical() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[1, 2, 3]);
assert_eq!(collect_sym(&a, &b), Vec::<i32>::new());
}
#[test]
fn symmetric_difference_partial_overlap() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[2, 3, 4]);
assert_eq!(collect_sym(&a, &b), vec![1, 4]);
}
#[test]
fn symmetric_difference_custom_comparator() {
let a = make_rev_set(&[1, 2, 3]);
let b = make_rev_set(&[2, 3, 4]);
let sym: Vec<i32> = a.symmetric_difference(&b).copied().collect();
assert_eq!(sym, vec![4, 1]);
}
#[test]
fn union_both_empty() {
let a = make_set(&[]);
let b = make_set(&[]);
assert_eq!(collect_union(&a, &b), Vec::<i32>::new());
}
#[test]
fn union_self_empty() {
let a = make_set(&[]);
let b = make_set(&[1, 2, 3]);
assert_eq!(collect_union(&a, &b), vec![1, 2, 3]);
}
#[test]
fn union_other_empty() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[]);
assert_eq!(collect_union(&a, &b), vec![1, 2, 3]);
}
#[test]
fn union_disjoint() {
let a = make_set(&[1, 3, 5]);
let b = make_set(&[2, 4, 6]);
assert_eq!(collect_union(&a, &b), vec![1, 2, 3, 4, 5, 6]);
}
#[test]
fn union_identical() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[1, 2, 3]);
assert_eq!(collect_union(&a, &b), vec![1, 2, 3]);
}
#[test]
fn union_partial_overlap() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[2, 3, 4]);
assert_eq!(collect_union(&a, &b), vec![1, 2, 3, 4]);
}
#[test]
fn union_one_is_subset() {
let a = make_set(&[1, 2]);
let b = make_set(&[1, 2, 3, 4]);
assert_eq!(collect_union(&a, &b), vec![1, 2, 3, 4]);
}
#[test]
fn union_custom_comparator() {
let a = make_rev_set(&[1, 2, 3]);
let b = make_rev_set(&[2, 3, 4]);
let u: Vec<i32> = a.union(&b).copied().collect();
assert_eq!(u, vec![4, 3, 2, 1]);
}
#[test]
fn union_size_hint() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[3, 4, 5]);
let iter = a.union(&b);
let (lo, hi) = iter.size_hint();
assert_eq!(lo, 0);
assert!(hi.is_some_and(|h| h >= 5)); }
#[test]
fn debug_difference() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[2]);
let d = a.difference(&b);
let s = format!("{d:?}");
assert_eq!(s, "[1, 3]");
}
#[test]
fn debug_intersection() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[2, 3, 4]);
let i = a.intersection(&b);
let s = format!("{i:?}");
assert_eq!(s, "[2, 3]");
}
#[test]
fn debug_symmetric_difference() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[2, 3, 4]);
let sd = a.symmetric_difference(&b);
let s = format!("{sd:?}");
assert_eq!(s, "[1, 4]");
}
#[test]
fn debug_union() {
let a = make_set(&[1, 2, 3]);
let b = make_set(&[3, 4, 5]);
let u = a.union(&b);
let s = format!("{u:?}");
assert_eq!(s, "[1, 2, 3, 4, 5]");
}
}