use num_traits::One;
use std::collections::{HashSet, VecDeque};
use std::iter::IntoIterator;
use std::ops::Deref;
use crate::anahash::*;
use crate::types::*;
pub struct DeletionIterator<'a> {
value: &'a AnaValue,
alphabet_size: CharIndexType,
iteration: usize,
}
impl<'a> DeletionIterator<'a> {
pub fn new(value: &'a AnaValue, alphabet_size: CharIndexType) -> DeletionIterator<'a> {
DeletionIterator {
value,
alphabet_size,
iteration: 0,
}
}
}
#[derive(Clone, Debug)]
pub struct DeletionResult {
pub value: AnaValue,
pub charindex: CharIndexType,
}
impl Deref for DeletionResult {
type Target = AnaValue;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<'a> Iterator for DeletionIterator<'a> {
type Item = DeletionResult;
fn next(&mut self) -> Option<Self::Item> {
if self.value == &AnaValue::one() || self.iteration == self.alphabet_size as usize {
None
} else {
let charindex: CharIndexType = self.alphabet_size - (self.iteration as u8) - 1;
self.iteration += 1;
if let Some(result) = self.value.delete(&AnaValue::character(charindex)) {
Some(DeletionResult {
value: result,
charindex: charindex,
})
} else {
self.next() }
}
}
}
pub enum VisitedMap<'a> {
Internal(HashSet<AnaValue>),
External(&'a mut HashSet<AnaValue>),
}
impl VisitedMap<'_> {
pub fn contains(&self, key: &AnaValue) -> bool {
match self {
VisitedMap::Internal(map) => map.contains(key),
VisitedMap::External(map) => map.contains(key),
}
}
pub fn insert(&mut self, key: AnaValue) -> bool {
match self {
VisitedMap::Internal(map) => map.insert(key),
VisitedMap::External(map) => map.insert(key),
}
}
}
pub struct RecurseDeletionIterator<'a> {
queue: VecDeque<(DeletionResult, u32)>, alphabet_size: CharIndexType,
singlebeam: bool, breadthfirst: bool,
mindepth: u32,
maxdepth: Option<u32>,
empty_leaves: bool,
unique: bool,
visited: VisitedMap<'a>,
}
impl<'a> RecurseDeletionIterator<'a> {
pub fn new(
value: AnaValue,
alphabet_size: CharIndexType,
singlebeam: bool,
mindepth: Option<u32>,
maxdepth: Option<u32>,
breadthfirst: bool,
unique: bool,
empty_leaves: bool,
external_visited_map: Option<&'a mut HashSet<AnaValue>>,
) -> RecurseDeletionIterator<'a> {
let queue: Vec<(DeletionResult, u32)> = vec![(
DeletionResult {
value: value,
charindex: 0,
},
0,
)];
RecurseDeletionIterator {
queue: VecDeque::from(queue),
alphabet_size: alphabet_size,
singlebeam: singlebeam,
breadthfirst: breadthfirst,
mindepth: mindepth.unwrap_or(1),
maxdepth: maxdepth,
unique: unique,
empty_leaves: empty_leaves,
visited: match external_visited_map {
Some(mapref) => VisitedMap::External(mapref),
None => VisitedMap::Internal(HashSet::new()),
},
}
}
}
impl Iterator for RecurseDeletionIterator<'_> {
type Item = (DeletionResult, u32);
fn next(&mut self) -> Option<Self::Item> {
if self.breadthfirst {
if let Some((node, depth)) = self.queue.pop_front() {
if self.unique && self.visited.contains(&node.value) {
return self.next(); }
if self.maxdepth.is_none() || depth < self.maxdepth.expect("get maxdepth") {
let iter_children = DeletionIterator::new(&node.value, self.alphabet_size);
if self.unique {
let visited = &self.visited; self.queue.extend(
iter_children
.filter(|child| !visited.contains(&child.value))
.map(|child| (child, depth + 1)),
);
} else {
self.queue
.extend(iter_children.map(|child| (child, depth + 1)));
}
}
if (depth < self.mindepth) || (!self.empty_leaves && node.value.is_empty()) {
self.next()
} else {
if self.unique {
self.visited.insert(node.value.clone());
}
Some((node, depth))
}
} else {
None
}
} else {
if let Some((node, depth)) = self.queue.pop_back() {
if self.maxdepth.is_none() || depth < self.maxdepth.expect("get maxdepth") {
if self.unique && self.visited.contains(&node.value) {
return self.next(); }
let mut iter_children = DeletionIterator::new(&node.value, self.alphabet_size);
if self.singlebeam {
if let Some(child) = iter_children.next() {
self.queue.push_back((child, depth + 1));
}
} else {
let children = iter_children.collect::<Vec<_>>();
let children = children.into_iter().rev();
if self.unique {
let visited = &self.visited; self.queue.extend(
children
.filter(|child| !visited.contains(&child.value))
.map(|child| (child, depth + 1)),
);
} else {
self.queue.extend(children.map(|child| (child, depth + 1)));
}
}
}
if (depth < self.mindepth) || (!self.empty_leaves && node.value.is_empty()) {
self.next()
} else {
if self.unique {
self.visited.insert(node.value.clone());
}
Some((node, depth))
}
} else {
None
}
}
}
}