use std::fmt::Display;
#[derive(Debug)]
pub struct FastSet {
max: u32,
size: u32,
pos: Box<[u32]>,
elem: Box<[u32]>,
}
#[derive(Debug)]
pub struct FastSetIterator<'a> {
elem: &'a [u32],
index: usize,
size: usize,
}
impl Display for FastSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{{")?;
for i in 0..self.size {
write!(f, " {}", self.elem[i as usize])?;
}
write!(f, " }}")
}
}
#[allow(dead_code)]
impl FastSet {
pub fn new(max: u32) -> Self {
let n = max as usize;
let pos = vec![0; n].into_boxed_slice();
let elem = vec![0; n].into_boxed_slice();
FastSet {
max,
size: 0,
pos,
elem,
}
}
pub fn card(&self) -> u32 {
self.size
}
pub fn contains(&self, x: u32) -> bool {
debug_assert!(x < self.max);
let i = self.pos[x as usize];
i < self.size && self.elem[i as usize] == x
}
pub fn insert(&mut self, x: u32) {
debug_assert!(x < self.max);
let i = self.pos[x as usize];
let s = self.size;
if i >= s || self.elem[i as usize] != x {
self.pos[x as usize] = s;
self.elem[s as usize] = x;
self.size += 1;
}
}
pub fn remove(&mut self, x: u32) {
debug_assert!(x < self.max);
let i = self.pos[x as usize];
let mut s = self.size;
if i < s && self.elem[i as usize] == x {
s -= 1;
let y = self.elem[s as usize];
self.pos[y as usize] = i;
self.elem[i as usize] = y;
self.size = s;
}
}
pub fn reset(&mut self) {
self.size = 0;
}
pub fn iter(&self) -> FastSetIterator<'_> {
FastSetIterator {
elem: &self.elem,
index: 0,
size: self.size as usize,
}
}
}
impl<'a> Iterator for FastSetIterator<'a> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
let i = self.index;
if i < self.size {
self.index += 1;
Some(self.elem[i])
} else {
None
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() {
let set = &mut FastSet::new(100);
set.insert(10);
set.insert(20);
set.insert(10);
set.insert(40);
set.insert(40);
println!("After adding 10, 20, 40: {}", set);
assert!(set.contains(10));
assert!(set.contains(20));
assert!(set.contains(40));
assert!(!set.contains(30));
assert_eq!(set.card(), 3);
for x in set.iter() {
println!("Element: {}", x);
assert!(set.contains(x));
}
set.remove(30);
set.remove(40);
println!("After removing 30, 40: {}", set);
assert!(set.contains(10));
assert!(set.contains(20));
assert!(!set.contains(30));
assert!(!set.contains(40));
assert_eq!(set.card(), 2);
set.remove(10);
println!("After removing 10: {}", set);
assert!(set.contains(20));
assert!(!set.contains(10));
assert!(!set.contains(30));
assert!(!set.contains(40));
assert_eq!(set.card(), 1);
set.reset();
println!("After reset: {}", set);
assert!(!set.contains(20));
assert!(!set.contains(10));
assert!(!set.contains(30));
assert!(!set.contains(40));
assert_eq!(set.card(), 0);
}
}