use crate::bfs::Bfs;
use crate::dfs::Dfs;
use crate::postorder::Postorder;
pub mod bfs;
pub mod dfs;
pub mod postorder;
pub mod prelude;
pub trait Climber: Iterator {
fn depth(&self) -> usize;
fn up(&mut self) -> Option<Self::Item>;
fn down<P>(&mut self, predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool;
fn parent(&self) -> Option<Self::Item>;
fn children(&self) -> impl Iterator<Item = Self::Item>;
fn is_leaf(&self) -> bool {
self.children().next().is_none()
}
fn is_root(&self) -> bool {
self.depth() == 0
}
fn has_parent(&self) -> bool {
self.parent().is_some()
}
fn has_children(&self) -> bool {
self.children().next().is_some()
}
fn child_count(&self) -> usize {
self.children().count()
}
fn find_child<P>(&self, predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool,
{
self.children().find(predicate)
}
fn ancestors(&mut self) -> impl Iterator<Item = Self::Item> + '_ {
std::iter::from_fn(|| self.up())
}
fn find_ancestor<P>(&mut self, mut predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool,
{
self.ancestors().find(|node| predicate(node))
}
fn has_ancestor<P>(&mut self, predicate: P) -> bool
where
P: FnMut(&Self::Item) -> bool,
{
self.find_ancestor(predicate).is_some()
}
fn to_root(&mut self) {
while self.up().is_some() {}
}
fn up_by(&mut self, levels: usize) {
for _ in 0..levels {
if self.up().is_none() {
break;
}
}
}
fn up_until<P>(&mut self, mut predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool,
{
while let Some(node) = self.up() {
if predicate(&node) {
return Some(node);
}
}
None
}
fn down_until<P, Q>(&mut self, mut descend: P, mut until: Q) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool,
Q: FnMut(&Self::Item) -> bool,
{
loop {
let node = self.down(&mut descend)?;
if until(&node) {
return Some(node);
}
}
}
}
pub trait IndexedClimber: Climber {
type Index;
fn index(&self) -> Self::Index;
fn go_to(&mut self, index: &Self::Index) -> Option<Self::Item>;
fn child_indices(&self) -> impl DoubleEndedIterator<Item = Self::Index>;
fn dfs(self) -> Dfs<Self>
where
Self: Sized,
{
Dfs::new(self)
}
fn bfs(self) -> Bfs<Self>
where
Self: Sized,
{
Bfs::new(self)
}
fn postorder(self) -> Postorder<Self>
where
Self: Sized,
{
Postorder::new(self)
}
}