use crate::{ReversibleColoring, Set};
pub struct Node<S: Set + ?Sized> {
path: Vec<S::Item>, coloring: ReversibleColoring<S>,
}
impl<S: Set + ?Sized> Node<S> {
pub fn root(coloring: ReversibleColoring<S>) -> Self {
Self {
path: Vec::new(),
coloring,
}
}
pub fn path(&self) -> &Vec<S::Item> {
&self.path
}
pub fn coloring(&self) -> &ReversibleColoring<S> {
&self.coloring
}
pub fn restore(&mut self, n: usize) {
debug_assert_eq!(self.path.len(), self.coloring.depth());
self.coloring.restore(n);
self.path.truncate(self.path.len() - n);
debug_assert_eq!(self.path.len(), self.coloring.depth());
}
pub fn children_color(&self) -> Option<&[S::Item]> {
self.coloring.colors().find(|&color| color.len() > 1)
}
fn individualize<F>(&mut self, child: S::Item, mut refine: F)
where
F: FnMut(&mut ReversibleColoring<S>),
{
debug_assert_eq!(self.path.len(), self.coloring.depth());
debug_assert!(!self.path.contains(&child));
self.coloring.begin();
self.coloring.individualize(&child);
refine(&mut self.coloring);
self.path.push(child);
debug_assert_eq!(self.path.len(), self.coloring.depth());
}
pub fn into_first_child_leaf<F>(mut self, mut refine: F) -> Self
where
F: FnMut(&mut ReversibleColoring<S>),
{
while let Some(color) = self.children_color() {
let child = color[0].clone();
self.individualize(child, &mut refine)
}
self
}
pub fn into_next_leaf<F>(mut self, mut refine: F) -> Option<Self>
where
F: FnMut(&mut ReversibleColoring<S>),
{
debug_assert_eq!(self.path.len(), self.coloring.depth());
let last = self.path.pop()?;
self.coloring.restore(1);
let color_index = self.coloring.color_index_of(&last).unwrap();
let color = self.coloring.get(color_index).unwrap();
let next_sibling_index = color.binary_search(&last).unwrap() + 1;
match color.get(next_sibling_index) {
Some(next_sibling) => {
let next_sibling = next_sibling.clone();
self.individualize(next_sibling, &mut refine);
while let Some(color) = self.children_color() {
let child = color[0].clone();
self.individualize(child, &mut refine)
}
Some(self)
}
None => {
debug_assert_eq!(self.path.len(), self.coloring.depth());
self.into_next_leaf(refine) }
}
}
}