use crate::collections::io::{Fragment, FragmentIter};
use crate::prelude::{Board, BoardBuilder};
use std::{
collections::{HashMap, HashSet},
io::{BufWriter, Read, Write},
};
fn u64_to_board(hash: u64) -> Board {
BoardBuilder::from(hash).build_unchecked()
}
#[derive(Debug, Clone, Default)]
pub struct Capacity(HashMap<u32, usize>);
impl PartialEq for Capacity {
fn eq(&self, other: &Self) -> bool {
self.0.iter().all(|(t, n)| {
other
.0
.get(t)
.map(|nn| *n == *nn)
.unwrap_or_else(|| *n == 0)
})
}
}
impl Eq for Capacity {}
impl Capacity {
pub fn new() -> Self {
Self::default()
}
pub fn len(&self) -> usize {
self.0.values().sum()
}
pub fn is_empty(&self) -> bool {
self.0.values().all(|&n| n == 0)
}
}
impl std::ops::Add for Capacity {
type Output = Capacity;
fn add(mut self, rhs: Self) -> Self::Output {
self += rhs;
self
}
}
impl std::ops::AddAssign for Capacity {
fn add_assign(&mut self, rhs: Self) {
for (top, num_bottoms) in rhs.0 {
*self.0.entry(top).or_default() += num_bottoms;
}
}
}
#[derive(Clone, Default, PartialEq, Eq)]
pub struct BoardSet {
raw: RawBoardSet,
}
impl std::fmt::Debug for BoardSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let vec: Vec<Board> = self.iter().collect();
f.debug_set().entries(&vec).finish()
}
}
impl<const N: usize> From<[Board; N]> for BoardSet {
fn from(value: [Board; N]) -> Self {
Self::from_iter(value)
}
}
impl FromIterator<Board> for BoardSet {
fn from_iter<T: IntoIterator<Item = Board>>(iter: T) -> Self {
Self {
raw: iter.into_iter().map(|b| b.to_u64()).collect(),
}
}
}
impl Extend<Board> for BoardSet {
fn extend<T: IntoIterator<Item = Board>>(&mut self, iter: T) {
self.raw.extend(iter.into_iter().map(|b| b.to_u64()))
}
}
impl<'a> Extend<&'a Board> for BoardSet {
fn extend<T: IntoIterator<Item = &'a Board>>(&mut self, iter: T) {
self.raw.extend(iter.into_iter().map(|b| b.to_u64()))
}
}
impl IntoIterator for BoardSet {
type Item = Board;
type IntoIter = IntoIter;
fn into_iter(self) -> Self::IntoIter {
IntoIter(RawIntoIter::new(self.raw))
}
}
impl<'a> IntoIterator for &'a BoardSet {
type Item = Board;
type IntoIter = Iter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl From<RawBoardSet> for BoardSet {
fn from(raw: RawBoardSet) -> Self {
Self::from_raw(raw)
}
}
impl BoardSet {
pub fn new() -> Self {
Self::default()
}
pub fn new_from_file(path: impl AsRef<std::path::Path>) -> std::io::Result<BoardSet> {
let raw_set = RawBoardSet::new_from_file(path)?;
Ok(raw_set.into())
}
pub fn raw(&self) -> &RawBoardSet {
&self.raw
}
pub fn raw_mut(&mut self) -> &mut RawBoardSet {
&mut self.raw
}
pub fn into_raw(self) -> RawBoardSet {
self.raw
}
pub fn from_raw(raw: RawBoardSet) -> Self {
Self { raw }
}
pub fn required_capacity<R>(reader: R) -> std::io::Result<Capacity>
where
R: Read,
{
RawBoardSet::required_capacity(reader)
}
pub fn required_capacity_filter<R, F>(reader: R, f: F) -> std::io::Result<Capacity>
where
R: Read,
F: FnMut(&u64) -> bool,
{
RawBoardSet::required_capacity_filter(reader, f)
}
pub fn with_capacity(capacity: Capacity) -> Self {
Self {
raw: RawBoardSet::with_capacity(capacity),
}
}
pub fn capacity(&self) -> Capacity {
self.raw.capacity()
}
pub fn iter(&self) -> Iter {
Iter(RawIter::new(&self.raw))
}
pub fn len(&self) -> usize {
self.raw.len()
}
pub fn is_empty(&self) -> bool {
self.raw.is_empty()
}
pub fn drain(&mut self) -> Drain {
Drain(RawDrain::new(&mut self.raw))
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&Board) -> bool,
{
self.raw.retain(|&h| f(&u64_to_board(h)))
}
pub fn remove_loaded_values<R>(&mut self, reader: R) -> std::io::Result<bool>
where
R: Read,
{
self.raw.remove_loaded_values(reader)
}
pub fn clear(&mut self) {
self.raw.clear()
}
pub fn reserve(&mut self, additional: Capacity) {
self.raw.reserve(additional)
}
pub fn shrink_to_fit(&mut self) {
self.raw.shrink_to_fit()
}
pub fn difference<'a>(&'a self, other: &'a BoardSet) -> Difference<'a> {
Difference(RawDifference::new(&self.raw, &other.raw))
}
pub fn symmetric_difference<'a>(&'a self, other: &'a BoardSet) -> SymmetricDifference<'a> {
SymmetricDifference(RawSymmetricDifference::new(&self.raw, &other.raw))
}
pub fn intersection<'a>(&'a self, other: &'a BoardSet) -> Intersection<'a> {
Intersection(RawIntersection::new(&self.raw, &other.raw))
}
pub fn union<'a>(&'a self, other: &'a BoardSet) -> Union<'a> {
Union(RawUnion::new(&self.raw, &other.raw))
}
pub fn contains(&self, board: &Board) -> bool {
self.raw.contains(&board.to_u64())
}
pub fn is_disjoint(&self, other: &BoardSet) -> bool {
self.raw.is_disjoint(&other.raw)
}
pub fn is_subset(&self, other: &BoardSet) -> bool {
self.raw.is_subset(&other.raw)
}
pub fn is_superset(&self, other: &BoardSet) -> bool {
self.raw.is_superset(&other.raw)
}
pub fn insert(&mut self, board: Board) -> bool {
self.raw.insert(board.to_u64())
}
pub fn remove(&mut self, board: &Board) -> bool {
self.raw.remove(&board.to_u64())
}
pub fn take(&mut self, board: &Board) -> Option<Board> {
self.raw.take(&board.to_u64()).map(u64_to_board)
}
pub fn absorb(&mut self, set: BoardSet) {
self.raw.absorb(set.raw);
}
pub fn absorb_drained(&mut self, set: &mut BoardSet) {
self.raw.absorb_drained(&mut set.raw);
}
pub fn load<R>(&mut self, reader: R) -> std::io::Result<()>
where
R: Read,
{
self.raw.load(reader)
}
pub fn load_filter<R, F>(&mut self, reader: R, f: F) -> std::io::Result<()>
where
R: Read,
F: FnMut(&u64) -> bool,
{
self.raw.load_filter(reader, f)
}
pub fn save<W>(&self, writer: W) -> std::io::Result<()>
where
W: Write,
{
self.raw.save(writer)
}
pub fn split(self, left_len: usize) -> (Self, Self) {
let (left_raw, right_raw) = self.into_raw().split(left_len);
(left_raw.into(), right_raw.into())
}
}
impl std::ops::BitAnd<&BoardSet> for &BoardSet {
type Output = BoardSet;
fn bitand(self, rhs: &BoardSet) -> Self::Output {
Self::Output {
raw: self.raw.bitand(&rhs.raw),
}
}
}
impl std::ops::BitOr<&BoardSet> for &BoardSet {
type Output = BoardSet;
fn bitor(self, rhs: &BoardSet) -> Self::Output {
Self::Output {
raw: self.raw.bitor(&rhs.raw),
}
}
}
impl std::ops::BitXor<&BoardSet> for &BoardSet {
type Output = BoardSet;
fn bitxor(self, rhs: &BoardSet) -> Self::Output {
Self::Output {
raw: self.raw.bitxor(&rhs.raw),
}
}
}
impl std::ops::Sub<&BoardSet> for &BoardSet {
type Output = BoardSet;
fn sub(self, rhs: &BoardSet) -> Self::Output {
Self::Output {
raw: self.raw.sub(&rhs.raw),
}
}
}
pub struct IntoIter(RawIntoIter);
pub struct Drain<'a>(RawDrain<'a>);
#[derive(Clone)]
pub struct Iter<'a>(RawIter<'a>);
#[derive(Clone)]
pub struct Difference<'a>(RawDifference<'a>);
#[derive(Clone)]
pub struct SymmetricDifference<'a>(RawSymmetricDifference<'a>);
#[derive(Clone)]
pub struct Intersection<'a>(RawIntersection<'a>);
#[derive(Clone)]
pub struct Union<'a>(RawUnion<'a>);
macro_rules! impl_debug {
(<$iter_name:expr, $iter:ident>) => {
impl<'a> std::fmt::Debug for $iter<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let vec: Vec<<Self as Iterator>::Item> = self.clone().collect();
f.debug_tuple($iter_name).field(&vec).finish()
}
}
};
($(<$iters2_name:expr, $iters2:ident>)*) => {
$(impl_debug!(<$iters2_name, $iters2>);)*
};
}
macro_rules! impl_debug_sealed {
({$iter_name:expr, $iter:ident}) => {
impl std::fmt::Debug for $iter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}([..])", $iter_name)
}
}
};
(<$iter_name:expr, $iter:ident>) => {
impl<'a> std::fmt::Debug for $iter<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}([..])", $iter_name)
}
}
};
($({$iters1_name:expr, $iters1:ident})* $(<$iters2_name:expr, $iters2:ident>)*) => {
$(impl_debug_sealed!({$iters1_name, $iters1});)*
$(impl_debug_sealed!(<$iters2_name, $iters2>);)*
};
}
macro_rules! impl_iterators {
({$iter:ident => $raw:ident}) => {
impl Iterator for $iter {
type Item = Board;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(u64_to_board)
}
}
};
(<$iter:ident => $raw:ident>) => {
impl<'a> Iterator for $iter<'a> {
type Item = Board;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(u64_to_board)
}
}
};
($({$iters1:ident => $raws1:ident})* $(<$iters2:ident => $raws2:ident>)*) => {
$(impl_iterators!({$iters1 => $raws1});)*
$(impl_iterators!(<$iters2 => $raws2>);)*
};
}
impl_debug!(
< "Iter", Iter >
< "RawIter", RawIter >
< "Difference", Difference >
< "RawDifference", RawDifference >
< "SymmetricDifference", SymmetricDifference >
< "RawSymmetricDifference", RawSymmetricDifference >
< "Intersection", Intersection >
< "RawIntersection", RawIntersection >
< "Union", Union >
< "RawUnion", RawUnion >
);
impl_debug_sealed!(
{ "IntoIter", IntoIter }
{ "RawIntoIter", RawIntoIter }
< "Drain", Drain >
< "RawDrain", RawDrain >
);
impl_iterators!(
{ IntoIter => RawIntoIter }
< Drain => RawDrain >
< Iter => RawIter >
< Difference => RawDifference >
< SymmetricDifference => RawSymmetricDifference >
< Intersection => RawIntersection >
< Union => RawUnion >
);
#[derive(Clone, Default)]
pub struct RawBoardSet {
pub(crate) top2bottoms: HashMap<u32, HashSet<u32>>,
}
impl std::fmt::Debug for RawBoardSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let vec: Vec<u64> = self.iter().collect();
f.debug_set().entries(&vec).finish()
}
}
impl PartialEq for RawBoardSet {
fn eq(&self, other: &Self) -> bool {
self.top2bottoms.iter().all(|(t, b)| {
other
.top2bottoms
.get(t)
.map(|bb| *b == *bb)
.unwrap_or_else(|| b.is_empty())
})
}
}
impl Eq for RawBoardSet {}
impl From<BoardSet> for RawBoardSet {
fn from(value: BoardSet) -> Self {
value.into_raw()
}
}
impl<const N: usize> From<[u64; N]> for RawBoardSet {
fn from(value: [u64; N]) -> Self {
Self::from_iter(value)
}
}
impl FromIterator<u64> for RawBoardSet {
fn from_iter<T: IntoIterator<Item = u64>>(iter: T) -> Self {
let mut set = Self::new();
for item in iter {
set.insert(item);
}
set
}
}
impl Extend<u64> for RawBoardSet {
fn extend<T: IntoIterator<Item = u64>>(&mut self, iter: T) {
iter.into_iter().for_each(|h| {
self.insert(h);
});
}
}
impl<'a> Extend<&'a u64> for RawBoardSet {
fn extend<T: IntoIterator<Item = &'a u64>>(&mut self, iter: T) {
self.extend(iter.into_iter().cloned())
}
}
impl IntoIterator for RawBoardSet {
type Item = u64;
type IntoIter = RawIntoIter;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter::new(self)
}
}
impl<'a> IntoIterator for &'a RawBoardSet {
type Item = u64;
type IntoIter = RawIter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl RawBoardSet {
pub fn new() -> Self {
Self::default()
}
pub fn new_from_file(path: impl AsRef<std::path::Path>) -> std::io::Result<RawBoardSet> {
let capacity = Self::required_capacity(std::fs::File::open(&path)?)?;
let mut set = Self::with_capacity(capacity);
set.load(std::fs::File::open(path)?)?;
Ok(set)
}
pub fn required_capacity<R>(reader: R) -> std::io::Result<Capacity>
where
R: Read,
{
let mut count = HashMap::new();
let mut top = 0;
let mut iter = FragmentIter::new(reader);
loop {
let Some(fragment) = iter.try_next()? else {
break;
};
use Fragment::*;
match fragment {
Delimiter => continue,
Top(top_) => top = top_,
Bottom(_) => *count.entry(top).or_default() += 1,
}
}
Ok(Capacity(count))
}
pub fn required_capacity_filter<R, F>(reader: R, mut f: F) -> std::io::Result<Capacity>
where
R: Read,
F: FnMut(&u64) -> bool,
{
let mut count = HashMap::new();
let mut top = 0;
let mut iter = FragmentIter::new(reader);
loop {
let Some(fragment) = iter.try_next()? else {
break;
};
use Fragment::*;
match fragment {
Delimiter => continue,
Top(top_) => top = top_,
Bottom(bottom) => {
let hash = Self::u32_u32_to_u64(top, bottom);
if f(&hash) {
*count.entry(top).or_default() += 1;
}
}
}
}
Ok(Capacity(count))
}
pub fn with_capacity(capacity: Capacity) -> Self {
let mut top2bottoms = HashMap::with_capacity(capacity.0.len());
for (top, num_bottoms) in capacity.0 {
top2bottoms.insert(top, HashSet::with_capacity(num_bottoms));
}
Self { top2bottoms }
}
pub fn capacity(&self) -> Capacity {
let mut count = HashMap::with_capacity(self.top2bottoms.len());
for (k, v) in self.top2bottoms.iter() {
count.insert(*k, v.capacity());
}
Capacity(count)
}
pub fn iter(&self) -> RawIter {
RawIter::new(self)
}
pub(crate) fn u64_to_u32_u32(n: u64) -> (u32, u32) {
((n >> 32) as u32, n as u32)
}
pub(crate) fn u32_u32_to_u64(top: u32, bottom: u32) -> u64 {
((top as u64) << 32) | (bottom as u64)
}
pub fn len(&self) -> usize {
self.top2bottoms.values().map(|s| s.len()).sum()
}
pub fn is_empty(&self) -> bool {
self.top2bottoms.values().all(|s| s.is_empty())
}
pub fn drain(&mut self) -> RawDrain {
RawDrain::new(self)
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&u64) -> bool,
{
for (&top, bottoms) in self.top2bottoms.iter_mut() {
bottoms.retain(|&b| {
let hash = RawBoardSet::u32_u32_to_u64(top, b);
f(&hash)
});
}
}
pub fn remove_loaded_values<R>(&mut self, reader: R) -> std::io::Result<bool>
where
R: Read,
{
let mut removed = false;
let mut dummy = HashSet::new();
let mut bottoms = &mut dummy;
let mut is_capturing = false;
let mut iter = FragmentIter::new(reader);
loop {
let Some(fragment) = iter.try_next()? else {
return Ok(removed);
};
use Fragment::*;
match fragment {
Delimiter => continue,
Top(top_) => match self.top2bottoms.get_mut(&top_) {
Some(bottoms_) => {
is_capturing = true;
bottoms = bottoms_;
}
None => {
is_capturing = false;
bottoms = &mut dummy;
}
},
Bottom(bottom_) => {
if !is_capturing {
continue;
}
removed |= bottoms.remove(&bottom_);
}
}
}
}
pub fn clear(&mut self) {
self.top2bottoms.clear()
}
pub fn reserve(&mut self, additional: Capacity) {
for (top, additional_len) in additional.0 {
match self.top2bottoms.get_mut(&top) {
Some(bottoms) => {
bottoms.reserve(additional_len);
}
None => {
self.top2bottoms
.insert(top, HashSet::with_capacity(additional_len));
}
};
}
}
pub fn shrink_to_fit(&mut self) {
self.top2bottoms.retain(|_, v| !v.is_empty());
self.top2bottoms.shrink_to_fit();
self.top2bottoms
.values_mut()
.for_each(|b| b.shrink_to_fit());
}
pub fn difference<'a>(&'a self, other: &'a RawBoardSet) -> RawDifference<'a> {
RawDifference::new(self, other)
}
pub fn symmetric_difference<'a>(
&'a self,
other: &'a RawBoardSet,
) -> RawSymmetricDifference<'a> {
RawSymmetricDifference::new(self, other)
}
pub fn intersection<'a>(&'a self, other: &'a RawBoardSet) -> RawIntersection<'a> {
RawIntersection::new(self, other)
}
pub fn union<'a>(&'a self, other: &'a RawBoardSet) -> RawUnion<'a> {
RawUnion::new(self, other)
}
pub fn contains(&self, hash: &u64) -> bool {
let (k, v) = Self::u64_to_u32_u32(*hash);
self.top2bottoms.get(&k).map_or(false, |x| x.contains(&v))
}
pub fn is_disjoint(&self, other: &RawBoardSet) -> bool {
if self.len() <= other.len() {
self.iter().all(|v| !other.contains(&v))
} else {
other.iter().all(|v| !self.contains(&v))
}
}
pub fn is_subset(&self, other: &RawBoardSet) -> bool {
if self.len() <= other.len() {
self.iter().all(|v| other.contains(&v))
} else {
false
}
}
pub fn is_superset(&self, other: &RawBoardSet) -> bool {
other.is_subset(self)
}
pub fn insert(&mut self, hash: u64) -> bool {
let (k, v) = Self::u64_to_u32_u32(hash);
self.top2bottoms.entry(k).or_default().insert(v)
}
pub fn remove(&mut self, hash: &u64) -> bool {
let (k, v) = Self::u64_to_u32_u32(*hash);
let Some(set) = self.top2bottoms.get_mut(&k) else {
return false;
};
let removed = set.remove(&v);
if set.is_empty() {
self.top2bottoms.remove(&k);
}
removed
}
pub fn take(&mut self, hash: &u64) -> Option<u64> {
let (k, v) = Self::u64_to_u32_u32(*hash);
let set = self.top2bottoms.get_mut(&k)?;
let taken = set.take(&v).map(|bottom| Self::u32_u32_to_u64(k, bottom));
if set.is_empty() {
self.top2bottoms.remove(&k);
}
taken
}
pub fn absorb(&mut self, set: RawBoardSet) {
for (top, bottoms) in set.top2bottoms {
if bottoms.is_empty() {
continue;
}
self.top2bottoms.entry(top).or_default().extend(bottoms);
}
}
pub fn absorb_drained(&mut self, set: &mut RawBoardSet) {
for (top, bottoms) in set.top2bottoms.iter_mut() {
if bottoms.is_empty() {
continue;
}
self.top2bottoms
.entry(*top)
.or_default()
.extend(bottoms.drain());
}
}
pub fn load<R>(&mut self, reader: R) -> std::io::Result<()>
where
R: Read,
{
let mut iter = FragmentIter::new(reader);
let mut dummy = HashSet::new();
let mut set = &mut dummy;
let mut top = 0;
loop {
let Some(next) = iter.try_next()? else {
return Ok(());
};
use Fragment::*;
match next {
Delimiter => {
if set.is_empty() {
set = &mut dummy;
self.top2bottoms.remove(&top);
}
}
Top(top_) => {
set = self.top2bottoms.entry(top_).or_default();
top = top_;
}
Bottom(bottom_) => {
set.insert(bottom_);
}
}
}
}
pub fn load_filter<R, F>(&mut self, reader: R, mut f: F) -> std::io::Result<()>
where
R: Read,
F: FnMut(&u64) -> bool,
{
let mut iter = FragmentIter::new(reader);
let mut dummy = HashSet::new();
let mut set = &mut dummy;
let mut top = 0;
loop {
let Some(next) = iter.try_next()? else {
return Ok(());
};
use Fragment::*;
match next {
Delimiter => {
if set.is_empty() {
set = &mut dummy;
self.top2bottoms.remove(&top);
}
}
Top(top_) => {
set = self.top2bottoms.entry(top_).or_default();
top = top_;
}
Bottom(bottom) => {
let hash = Self::u32_u32_to_u64(top, bottom);
if f(&hash) {
set.insert(bottom);
}
}
}
}
}
pub fn save<W>(&self, writer: W) -> std::io::Result<()>
where
W: Write,
{
let mut writer = BufWriter::new(writer);
for (top, bottoms) in self.top2bottoms.iter() {
writer.write_all(&top.to_be_bytes())?;
for bottom in bottoms.iter() {
writer.write_all(&bottom.to_be_bytes())?;
}
writer.write_all(&u32::MAX.to_be_bytes())?;
}
writer.flush()?;
Ok(())
}
pub fn split(self, len_left: usize) -> (Self, Self) {
let mut left = RawBoardSet::new();
let mut right = RawBoardSet::new();
let mut add_to_left = true;
let mut len_left_tmp = 0;
for (top, bottoms) in self.top2bottoms {
if !add_to_left {
right.top2bottoms.insert(top, bottoms);
continue;
}
let residual = len_left - len_left_tmp;
if bottoms.len() <= residual {
len_left_tmp += bottoms.len();
left.top2bottoms.insert(top, bottoms);
} else {
let mut bottoms_iter = bottoms.into_iter();
let left_bottoms = (&mut bottoms_iter).take(residual).collect();
let right_bottoms = bottoms_iter.collect();
left.top2bottoms.insert(top, left_bottoms);
right.top2bottoms.insert(top, right_bottoms);
}
if len_left_tmp == len_left {
add_to_left = false;
}
}
(left, right)
}
}
impl std::ops::BitAnd<&RawBoardSet> for &RawBoardSet {
type Output = RawBoardSet;
fn bitand(self, rhs: &RawBoardSet) -> Self::Output {
self.intersection(rhs).collect()
}
}
impl std::ops::BitOr<&RawBoardSet> for &RawBoardSet {
type Output = RawBoardSet;
fn bitor(self, rhs: &RawBoardSet) -> Self::Output {
self.union(rhs).collect()
}
}
impl std::ops::BitXor<&RawBoardSet> for &RawBoardSet {
type Output = RawBoardSet;
fn bitxor(self, rhs: &RawBoardSet) -> Self::Output {
self.symmetric_difference(rhs).collect()
}
}
impl std::ops::Sub<&RawBoardSet> for &RawBoardSet {
type Output = RawBoardSet;
fn sub(self, rhs: &RawBoardSet) -> Self::Output {
self.difference(rhs).collect()
}
}
type MapIter<'a> = std::collections::hash_map::Iter<'a, u32, HashSet<u32>>;
type SetIter<'a> = std::collections::hash_set::Iter<'a, u32>;
#[derive(Clone)]
pub struct RawIter<'a> {
map_iter: MapIter<'a>, state: Option<(
u32, // key of top2bottoms
SetIter<'a>, // iterator of value of top2bottoms
)>,
}
impl<'a> RawIter<'a> {
fn new(set: &'a RawBoardSet) -> Self {
Self {
map_iter: set.top2bottoms.iter(),
state: None,
}
}
}
impl<'a> Iterator for RawIter<'a> {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
loop {
let Some((top, set_iter)) = self.state.as_mut() else {
let (top, set) = self.map_iter.next()?;
self.state = Some((*top, set.iter()));
continue;
};
let Some(bottom) = set_iter.next() else {
let (next_top, next_set) = self.map_iter.next()?;
*top = *next_top;
*set_iter = next_set.iter();
continue;
};
return Some(RawBoardSet::u32_u32_to_u64(*top, *bottom));
}
}
}
type MapIntoIter = std::collections::hash_map::IntoIter<u32, HashSet<u32>>;
type SetIntoIter = std::collections::hash_set::IntoIter<u32>;
pub struct RawIntoIter {
map_iter: MapIntoIter, state: Option<(
u32, // key of set.top2bottoms
SetIntoIter, // iterator of value of set.top2bottoms
)>,
}
impl RawIntoIter {
fn new(set: RawBoardSet) -> Self {
Self {
map_iter: set.top2bottoms.into_iter(),
state: None,
}
}
}
impl Iterator for RawIntoIter {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
loop {
let Some((top, set_iter)) = self.state.as_mut() else {
let (top, set) = self.map_iter.next()?;
self.state = Some((top, set.into_iter()));
continue;
};
let Some(bottom) = set_iter.next() else {
let (next_top, next_set) = self.map_iter.next()?;
*top = next_top;
*set_iter = next_set.into_iter();
continue;
};
return Some(RawBoardSet::u32_u32_to_u64(*top, bottom));
}
}
}
pub struct RawDrain<'a>(_RawDrain<'a>);
impl<'a> RawDrain<'a> {
fn new(set: &'a mut RawBoardSet) -> Self {
Self(_RawDrain::new(set))
}
}
impl<'a> Iterator for RawDrain<'a> {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
type MapDrain<'a> = std::collections::hash_map::IterMut<'a, u32, HashSet<u32>>;
type SetDrain<'a> = std::collections::hash_set::Drain<'a, u32>;
struct _RawDrain<'a> {
map_iter: MapDrain<'a>, state: Option<(
u32, // key of top2bottoms
SetDrain<'a>, // iterator of value of top2bottoms
)>,
}
impl<'a> _RawDrain<'a> {
fn new(set: &'a mut RawBoardSet) -> Self {
Self {
map_iter: set.top2bottoms.iter_mut(),
state: None,
}
}
}
impl<'a> Iterator for _RawDrain<'a> {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
loop {
let Some((top, set_iter)) = self.state.as_mut() else {
let (top, set) = self.map_iter.next()?;
self.state = Some((*top, set.drain()));
continue;
};
let Some(bottom) = set_iter.next() else {
let (next_top, next_set) = self.map_iter.next()?;
*top = *next_top;
*set_iter = next_set.drain();
continue;
};
return Some(RawBoardSet::u32_u32_to_u64(*top, bottom));
}
}
}
impl<'a> Drop for _RawDrain<'a> {
fn drop(&mut self) {
self.map_iter.by_ref().for_each(|(_, v)| {
v.drain();
});
}
}
#[derive(Clone)]
pub struct RawDifference<'a> {
left: RawIter<'a>,
right: &'a RawBoardSet,
}
impl<'a> RawDifference<'a> {
fn new(left: &'a RawBoardSet, right: &'a RawBoardSet) -> Self {
Self {
left: left.iter(),
right,
}
}
}
impl<'a> Iterator for RawDifference<'a> {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
loop {
let item = self.left.next()?;
if !self.right.contains(&item) {
return Some(item);
}
}
}
}
#[derive(Clone)]
pub struct RawSymmetricDifference<'a> {
left: &'a RawBoardSet,
left_iter: RawIter<'a>,
right: &'a RawBoardSet,
right_iter: RawIter<'a>,
}
impl<'a> RawSymmetricDifference<'a> {
fn new(left: &'a RawBoardSet, right: &'a RawBoardSet) -> Self {
Self {
left,
left_iter: left.iter(),
right,
right_iter: right.iter(),
}
}
}
impl<'a> Iterator for RawSymmetricDifference<'a> {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(item_left) = self.left_iter.next() {
if !self.right.contains(&item_left) {
return Some(item_left);
}
} else {
let item_right = self.right_iter.next()?;
if !self.left.contains(&item_right) {
return Some(item_right);
}
}
}
}
}
#[derive(Clone)]
pub struct RawIntersection<'a> {
left_iter: RawIter<'a>,
right: &'a RawBoardSet,
}
impl<'a> RawIntersection<'a> {
fn new(left: &'a RawBoardSet, right: &'a RawBoardSet) -> Self {
Self {
left_iter: left.iter(),
right,
}
}
}
impl<'a> Iterator for RawIntersection<'a> {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
loop {
let item = self.left_iter.next()?;
if self.right.contains(&item) {
return Some(item);
}
}
}
}
#[derive(Clone)]
pub struct RawUnion<'a> {
left_iter: RawIter<'a>,
right: &'a RawBoardSet,
right_iter: RawIter<'a>,
}
impl<'a> RawUnion<'a> {
fn new(left: &'a RawBoardSet, right: &'a RawBoardSet) -> Self {
Self {
left_iter: left.iter(),
right,
right_iter: right.iter(),
}
}
}
impl<'a> Iterator for RawUnion<'a> {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.left_iter.next() {
Some(item) => {
if !self.right.contains(&item) {
return Some(item);
}
}
None => return self.right_iter.next(),
}
}
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use crate::{collections::*, *};
fn create_from_strs(strs: &[&str]) -> BoardSet {
let mut set = BoardSet::new();
for board_str in strs {
let board = BoardBuilder::from_str(board_str).unwrap().build_unchecked();
set.insert(board);
}
set
}
#[test]
fn test_empty_capacity() {
let mut set = BoardSet::new();
assert_eq!(set.capacity(), Capacity::new());
set.insert(Board::new());
set.drain();
assert_ne!(set.capacity(), Capacity::new());
}
#[test]
fn test_set_calculation() {
let set1 = create_from_strs(&["Bb", "Bbh", "Bba"]);
let set2 = create_from_strs(&["Bb", "BbH", "BbA"]);
let set1and2 = create_from_strs(&["Bb"]);
let set1or2 = create_from_strs(&["Bb", "Bbh", "Bba", "BbH", "BbA"]);
let set1xor2 = create_from_strs(&["Bbh", "Bba", "BbH", "BbA"]);
let set1minus2 = create_from_strs(&["Bbh", "Bba"]);
assert_eq!(&set1 & &set2, set1and2);
assert_eq!(set1.raw() & set2.raw(), *set1and2.raw());
assert_eq!(&set1 | &set2, set1or2);
assert_eq!(set1.raw() | set2.raw(), *set1or2.raw());
assert_eq!(&set1 ^ &set2, set1xor2);
assert_eq!(set1.raw() ^ set2.raw(), *set1xor2.raw());
assert_eq!(&set1 - &set2, set1minus2);
assert_eq!(set1.raw() - set2.raw(), *set1minus2.raw());
assert!(set1or2.is_superset(&set1));
assert!(set1or2.raw().is_superset(set1.raw()));
assert!(set1.is_subset(&set1or2));
assert!(set1.raw().is_subset(set1or2.raw()));
assert!(set1xor2.is_disjoint(&set1and2));
assert!(set1xor2.raw().is_disjoint(set1and2.raw()));
}
#[test]
fn test_absorb_extend() {
let set1 = create_from_strs(&["Bb", "Bbh", "Bba"]);
let set2 = create_from_strs(&["Bb", "BbH", "BbA"]);
let set1or2 = create_from_strs(&["Bb", "Bbh", "Bba", "BbH", "BbA"]);
let mut set1absorb2 = set1.clone();
set1absorb2.absorb(set2.clone());
assert_eq!(set1absorb2, set1or2);
let mut set1absorb2_raw = set1.raw().clone();
set1absorb2_raw.absorb(set2.raw().clone());
assert_eq!(set1absorb2_raw, *set1or2.raw());
let mut set1extend2 = set1.clone();
set1extend2.extend(set2.iter());
assert_eq!(set1absorb2, set1extend2);
let mut set1extend2_raw = set1.raw().clone();
set1extend2_raw.extend(set2.raw().iter());
assert_eq!(set1absorb2_raw, set1extend2_raw);
}
#[test]
fn test_drain() {
let mut set = create_from_strs(&["Bb", "Bbh", "Bba"]);
let set1 = set.clone();
let set2 = BoardSet::from_iter(set.drain());
assert!(set.is_empty());
assert_eq!(set1, set2);
}
#[test]
fn test_drain_drop() {
let mut set = create_from_strs(&["Bb", "Bbh", "Bba"]);
let capacity = set.capacity();
{
set.drain();
}
assert!(set.is_empty());
assert_eq!(capacity, set.capacity());
}
#[test]
fn test_split() {
let set = create_from_strs(&["Bb", "Bbh", "Bba"]);
let (left, right) = set.clone().split(0);
assert_eq!(left.len(), 0);
assert_eq!(right.len(), 3);
assert_eq!(&left | &right, set);
let (left, right) = set.clone().split(1);
assert_eq!(left.len(), 1);
assert_eq!(right.len(), 2);
assert_eq!(&left | &right, set);
let (left, right) = set.clone().split(10);
assert_eq!(left.len(), 3);
assert_eq!(&left | &right, set);
let set = set.into_raw();
let (left, right) = set.clone().split(0);
assert_eq!(left.len(), 0);
assert_eq!(right.len(), 3);
assert_eq!(&left | &right, set);
let (left, right) = set.clone().split(1);
assert_eq!(left.len(), 1);
assert_eq!(right.len(), 2);
assert_eq!(&left | &right, set);
let (left, right) = set.clone().split(10);
assert_eq!(left.len(), 3);
assert_eq!(&left | &right, set);
}
}