use crate::prelude::*;
pub enum Tree<T, NT> {
Nullary,
Unary(T),
Binary(T, T),
Ternary(T, T, T),
Nary(NT),
}
pub trait TreeLike: Clone + Sized {
type NaryChildren: Clone;
fn nary_len(tc: &Self::NaryChildren) -> usize;
fn nary_index(tc: Self::NaryChildren, idx: usize) -> Self;
fn as_node(&self) -> Tree<Self, Self::NaryChildren>;
fn n_children(&self) -> usize {
match self.as_node() {
Tree::Nullary => 0,
Tree::Unary(..) => 1,
Tree::Binary(..) => 2,
Tree::Ternary(..) => 3,
Tree::Nary(ref children) => Self::nary_len(children),
}
}
fn nth_child(&self, n: usize) -> Option<Self> {
match (n, self.as_node()) {
(_, Tree::Nullary) => None,
(0, Tree::Unary(sub)) => Some(sub),
(_, Tree::Unary(..)) => None,
(0, Tree::Binary(sub, _)) => Some(sub),
(1, Tree::Binary(_, sub)) => Some(sub),
(_, Tree::Binary(..)) => None,
(0, Tree::Ternary(sub, _, _)) => Some(sub),
(1, Tree::Ternary(_, sub, _)) => Some(sub),
(2, Tree::Ternary(_, _, sub)) => Some(sub),
(_, Tree::Ternary(..)) => None,
(n, Tree::Nary(children)) if n < Self::nary_len(&children) => {
Some(Self::nary_index(children, n))
}
(_, Tree::Nary(..)) => None,
}
}
fn pre_order_iter(self) -> PreOrderIter<Self> { PreOrderIter { stack: vec![self] } }
fn verbose_pre_order_iter(self) -> VerbosePreOrderIter<Self> {
VerbosePreOrderIter { stack: vec![PreOrderIterItem::initial(self, None)], index: 0 }
}
fn post_order_iter(self) -> PostOrderIter<Self> {
PostOrderIter { index: 0, stack: vec![IterStackItem::unprocessed(self, None)] }
}
fn rtl_post_order_iter(self) -> RtlPostOrderIter<Self> {
RtlPostOrderIter { inner: Rtl(self).post_order_iter() }
}
}
#[derive(Clone, Debug)]
struct IterStackItem<T> {
elem: T,
processed: bool,
child_indices: Vec<usize>,
parent_stack_idx: Option<usize>,
}
impl<T: TreeLike> IterStackItem<T> {
fn unprocessed(elem: T, parent_stack_idx: Option<usize>) -> Self {
IterStackItem {
processed: false,
child_indices: Vec::with_capacity(elem.n_children()),
parent_stack_idx,
elem,
}
}
}
#[derive(Clone, Debug)]
pub struct PostOrderIter<T> {
index: usize,
stack: Vec<IterStackItem<T>>,
}
pub struct PostOrderIterItem<T> {
pub node: T,
pub index: usize,
pub child_indices: Vec<usize>,
}
impl<T: TreeLike> Iterator for PostOrderIter<T> {
type Item = PostOrderIterItem<T>;
fn next(&mut self) -> Option<Self::Item> {
let mut current = self.stack.pop()?;
if !current.processed {
current.processed = true;
let current_stack_idx = self.stack.len();
let n_children = current.elem.n_children();
self.stack.push(current);
for idx in (0..n_children).rev() {
self.stack.push(IterStackItem::unprocessed(
self.stack[current_stack_idx].elem.nth_child(idx).unwrap(),
Some(current_stack_idx),
));
}
self.next()
} else {
if let Some(idx) = current.parent_stack_idx {
self.stack[idx].child_indices.push(self.index);
}
self.index += 1;
Some(PostOrderIterItem {
node: current.elem,
index: self.index - 1,
child_indices: current.child_indices,
})
}
}
}
#[derive(Clone, Debug)]
struct Rtl<T>(pub T);
impl<T: TreeLike> TreeLike for Rtl<T> {
type NaryChildren = T::NaryChildren;
fn nary_len(tc: &Self::NaryChildren) -> usize { T::nary_len(tc) }
fn nary_index(tc: Self::NaryChildren, idx: usize) -> Self {
let rtl_idx = T::nary_len(&tc) - idx - 1;
Rtl(T::nary_index(tc, rtl_idx))
}
fn as_node(&self) -> Tree<Self, Self::NaryChildren> {
match self.0.as_node() {
Tree::Nullary => Tree::Nullary,
Tree::Unary(a) => Tree::Unary(Rtl(a)),
Tree::Binary(a, b) => Tree::Binary(Rtl(b), Rtl(a)),
Tree::Ternary(a, b, c) => Tree::Ternary(Rtl(c), Rtl(b), Rtl(a)),
Tree::Nary(data) => Tree::Nary(data),
}
}
}
#[derive(Clone, Debug)]
pub struct RtlPostOrderIter<T> {
inner: PostOrderIter<Rtl<T>>,
}
impl<T: TreeLike> Iterator for RtlPostOrderIter<T> {
type Item = PostOrderIterItem<T>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|mut item| {
item.child_indices.reverse();
PostOrderIterItem {
child_indices: item.child_indices,
index: item.index,
node: item.node.0,
}
})
}
}
#[derive(Clone, Debug)]
pub struct PreOrderIter<T> {
stack: Vec<T>,
}
impl<T: TreeLike> Iterator for PreOrderIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let top = self.stack.pop()?;
match top.as_node() {
Tree::Nullary => {}
Tree::Unary(next) => self.stack.push(next),
Tree::Binary(left, right) => {
self.stack.push(right);
self.stack.push(left);
}
Tree::Ternary(a, b, c) => {
self.stack.push(c);
self.stack.push(b);
self.stack.push(a);
}
Tree::Nary(children) => {
for i in (0..T::nary_len(&children)).rev() {
self.stack.push(T::nary_index(children.clone(), i));
}
}
}
Some(top)
}
}
#[derive(Clone, Debug)]
pub struct VerbosePreOrderIter<T> {
stack: Vec<PreOrderIterItem<T>>,
index: usize,
}
impl<T: TreeLike + Clone> Iterator for VerbosePreOrderIter<T> {
type Item = PreOrderIterItem<T>;
fn next(&mut self) -> Option<Self::Item> {
let mut top = self.stack.pop()?;
if top.n_children_yielded == 0 {
top.index = self.index;
self.index += 1;
}
let n_children = top.node.n_children();
if top.n_children_yielded < n_children {
self.stack.push(top.clone().increment(n_children));
let child = top.node.nth_child(top.n_children_yielded).unwrap();
self.stack
.push(PreOrderIterItem::initial(child, Some(top.node.clone())));
}
Some(top)
}
}
#[derive(Clone, Debug)]
pub struct PreOrderIterItem<T> {
pub node: T,
pub parent: Option<T>,
pub index: usize,
pub n_children_yielded: usize,
pub is_complete: bool,
}
impl<T: TreeLike + Clone> PreOrderIterItem<T> {
fn initial(node: T, parent: Option<T>) -> Self {
PreOrderIterItem {
is_complete: node.n_children() == 0,
node,
parent,
index: 0,
n_children_yielded: 0,
}
}
fn increment(self, n_children: usize) -> Self {
PreOrderIterItem {
node: self.node,
index: self.index,
parent: self.parent,
n_children_yielded: self.n_children_yielded + 1,
is_complete: self.n_children_yielded + 1 == n_children,
}
}
}