294 lines
9.0 KiB
Rust
294 lines
9.0 KiB
Rust
//! Binary trees without balancing.
|
|
//!
|
|
//! Intended for testing.
|
|
|
|
use std::fmt::Display;
|
|
|
|
use crate::func::*;
|
|
|
|
use super::*;
|
|
|
|
pub struct UnbalancedData;
|
|
|
|
impl PartialEq for UnbalancedData {
|
|
fn eq(&self, _other: &Self) -> bool {
|
|
false
|
|
}
|
|
|
|
#[allow(clippy::partialeq_ne_impl)]
|
|
fn ne(&self, _other: &Self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
pub struct UnbalancedNode<'a, T: Monad<'a>, A: 'a> {
|
|
cl: Rc<UnbalancedTree<'a, T, A>>,
|
|
cr: Rc<UnbalancedTree<'a, T, A>>,
|
|
key: Rc<A>,
|
|
}
|
|
|
|
pub type UnbalancedResolution<'a, T, A> = Wrap<'a, Rc<UnbalancedNode<'a, T, A>>, T>;
|
|
|
|
pub struct UnbalancedReference<'a, T: Monad<'a>, A: 'a>(
|
|
Box<dyn 'a + Fn() -> UnbalancedResolution<'a, T, A>>,
|
|
);
|
|
|
|
pub enum UnbalancedTree<'a, T: Monad<'a>, A: 'a> {
|
|
Leaf,
|
|
Node(Rc<UnbalancedReference<'a, T, A>>),
|
|
}
|
|
|
|
impl<'a, T: Monad<'a>, A: 'a + Display> Display for UnbalancedNode<'a, T, A>
|
|
where
|
|
UnbalancedReference<'a, T, A>: std::fmt::Display,
|
|
{
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.write_fmt(format_args!("({} {} {})", self.cl, self.key, self.cr))
|
|
}
|
|
}
|
|
|
|
impl<'a, T: Monad<'a>, A: 'a + Display> Display for UnbalancedTree<'a, T, A>
|
|
where
|
|
UnbalancedReference<'a, T, A>: std::fmt::Display,
|
|
{
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
UnbalancedTree::Leaf => f.write_fmt(format_args!(".")),
|
|
UnbalancedTree::Node(reference) => f.write_fmt(format_args!("{}", reference)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, A: 'a + Display> Display for UnbalancedReference<'a, instances::solo::SoloInstance, A> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.write_fmt(format_args!("{}", self.0()))
|
|
}
|
|
}
|
|
|
|
impl<'a, A: 'a + Display> Display
|
|
for UnbalancedReference<'a, instances::result::ResultInstance<()>, A>
|
|
{
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self.0() {
|
|
Ok(node) => f.write_fmt(format_args!("{}", node)),
|
|
Err(()) => f.write_fmt(format_args!("~")),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, T: Monad<'a>, A: 'a> TraversibleBinaryNode<'a, T, A, UnbalancedData>
|
|
for UnbalancedNode<'a, T, A>
|
|
{
|
|
fn split(&self) -> Split<'a, T, A, UnbalancedData> {
|
|
(self.cl.clone(), self.cr.clone(), self.key.clone())
|
|
}
|
|
|
|
fn to_tree(self: Rc<Self>) -> Rc<dyn TraversibleBinaryTree<'a, T, A, UnbalancedData>> {
|
|
Rc::new(UnbalancedTree::Node(Rc::new(UnbalancedReference(
|
|
Box::new(move || T::pure(self.clone())),
|
|
))))
|
|
}
|
|
}
|
|
|
|
impl<'a, T: Monad<'a>, A: 'a> TraversibleBinaryReference<'a, T, A, UnbalancedData>
|
|
for UnbalancedReference<'a, T, A>
|
|
{
|
|
fn resolve(&self) -> Wrap<'a, Rc<dyn TraversibleBinaryNode<'a, T, A, UnbalancedData>>, T> {
|
|
<T as Functor>::fmap(self.0(), |rc| {
|
|
rc as Rc<dyn TraversibleBinaryNode<'a, T, A, UnbalancedData>>
|
|
})
|
|
}
|
|
|
|
fn data(&self) -> UnbalancedData {
|
|
UnbalancedData
|
|
}
|
|
}
|
|
|
|
impl<'a, T: Monad<'a>, A: 'a> TraversibleBinaryTree<'a, T, A, UnbalancedData>
|
|
for UnbalancedTree<'a, T, A>
|
|
{
|
|
fn refer(&self) -> Option<Rc<dyn TraversibleBinaryReference<'a, T, A, UnbalancedData>>> {
|
|
match self {
|
|
UnbalancedTree::Leaf => None,
|
|
UnbalancedTree::Node(reference) => Some(reference.clone()),
|
|
}
|
|
}
|
|
}
|
|
|
|
type WrapType<'a, T, A> = Box<
|
|
dyn 'a + Fn(Rc<UnbalancedNode<'a, T, A>>) -> Box<dyn Fn() -> UnbalancedResolution<'a, T, A>>,
|
|
>;
|
|
|
|
pub struct UnbalancedConstructor<'a, T: Monad<'a>, A: 'a> {
|
|
wrap: WrapType<'a, T, A>,
|
|
}
|
|
|
|
impl<'a, T: Monad<'a>, A: 'a> UnbalancedConstructor<'a, T, A> {
|
|
pub fn rc(wrap: WrapType<'a, T, A>) -> Rc<Self> {
|
|
Self { wrap }.into()
|
|
}
|
|
|
|
pub fn leaf(&self) -> Rc<UnbalancedTree<'a, T, A>> {
|
|
UnbalancedTree::Leaf.into()
|
|
}
|
|
|
|
pub fn node(
|
|
self: &Rc<Self>,
|
|
cl: Rc<UnbalancedTree<'a, T, A>>,
|
|
key: A,
|
|
cr: Rc<UnbalancedTree<'a, T, A>>,
|
|
) -> Rc<UnbalancedTree<'a, T, A>> {
|
|
let node = Rc::new(UnbalancedNode {
|
|
cl,
|
|
cr,
|
|
key: key.into(),
|
|
});
|
|
let ctr = self.clone();
|
|
UnbalancedTree::Node(Rc::new(UnbalancedReference((ctr.wrap)(node)))).into()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
pub fn from_slice<R: 'a + rand::Rng>(
|
|
self: &Rc<Self>,
|
|
rng: &mut R,
|
|
slice: &[A],
|
|
) -> Rc<UnbalancedTree<'a, T, A>>
|
|
where
|
|
A: 'a + Clone,
|
|
{
|
|
if slice.is_empty() {
|
|
self.leaf()
|
|
} else {
|
|
let key_at = rng.gen_range(0..slice.len());
|
|
let key = slice[key_at].clone();
|
|
let lslice = &slice[..key_at];
|
|
let rslice = &slice[key_at + 1..];
|
|
self.clone().node(
|
|
self.clone().from_slice(rng, lslice),
|
|
key,
|
|
self.clone().from_slice(rng, rslice),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use rand::{Rng, SeedableRng};
|
|
|
|
use crate::rstd::tracing::*;
|
|
|
|
use super::{algorithms::contains::*, algorithms::subset::*, *};
|
|
|
|
#[test]
|
|
fn test_simple_slices() {
|
|
let ctr: Rc<UnbalancedConstructor<instances::result::ResultInstance<()>, _>> =
|
|
UnbalancedConstructor::rc(Box::new(|node| Box::new(move || Ok(node.clone()))));
|
|
let mut rng = rand::thread_rng();
|
|
let t_set = ctr.from_slice(&mut rng, &[0]);
|
|
assert!(t_contains(&DefaultComparator, t_set.clone(), 0.into()).is_ok());
|
|
assert!(t_contains(&DefaultComparator, t_set.clone(), 1.into()).is_err());
|
|
assert!(
|
|
t_subset_of_t(&DefaultComparator, t_set.clone(), t_set.clone(), None, None).is_ok()
|
|
);
|
|
assert!(t_subset_of_t(&DefaultComparator, t_set.clone(), ctr.leaf(), None, None).is_err());
|
|
assert!(t_subset_of_t(&DefaultComparator, ctr.leaf(), t_set.clone(), None, None).is_ok());
|
|
assert!(t_subset_of_t(&DefaultComparator, ctr.leaf(), ctr.leaf(), None, None).is_ok());
|
|
assert!(t_subset_of_t(
|
|
&DefaultComparator,
|
|
ctr.from_slice(&mut rng, &[0, 1, 2, 4, 5, 6, 7]),
|
|
ctr.from_slice(&mut rng, &[0, 1, 2, 3, 4, 5, 6, 7]),
|
|
None,
|
|
None
|
|
)
|
|
.is_ok());
|
|
assert!(t_subset_of_t(
|
|
&DefaultComparator,
|
|
ctr.from_slice(&mut rng, &[0, 1, 2, 3, 4, 5, 6, 7]),
|
|
ctr.from_slice(&mut rng, &[0, 1, 2, 4, 5, 6, 7]),
|
|
None,
|
|
None
|
|
)
|
|
.is_err());
|
|
}
|
|
|
|
#[ignore]
|
|
#[test]
|
|
fn test_random_slices() {
|
|
let ctr: Rc<UnbalancedConstructor<instances::result::ResultInstance<()>, _>> =
|
|
UnbalancedConstructor::rc(Box::new(|node| Box::new(move || Ok(node.clone()))));
|
|
let mut rng = rand::thread_rng();
|
|
for _ in 0..1000 {
|
|
let big: Vec<i32> = (0..(rng.gen_range(2..10))).collect();
|
|
let key = big[rng.gen_range(0..big.len())];
|
|
let small: Vec<i32> = big
|
|
.iter()
|
|
.filter(|x| **x != key && rng.gen_ratio(4, 5))
|
|
.map(|x| *x)
|
|
.collect();
|
|
let t_small = ctr.from_slice(&mut rng, &small);
|
|
let t_big = ctr.from_slice(&mut rng, &big);
|
|
assert!(
|
|
t_subset_of_t(
|
|
&DefaultComparator,
|
|
t_small.clone(),
|
|
t_big.clone(),
|
|
None,
|
|
None
|
|
)
|
|
.is_ok(),
|
|
"{} should be a subset of {}",
|
|
t_small,
|
|
t_big,
|
|
);
|
|
assert!(
|
|
t_subset_of_t(
|
|
&DefaultComparator,
|
|
t_big.clone(),
|
|
t_small.clone(),
|
|
None,
|
|
None
|
|
)
|
|
.is_err(),
|
|
"{} should not be a subset of {}",
|
|
t_big,
|
|
t_small,
|
|
);
|
|
}
|
|
}
|
|
|
|
type TracedMonad = instances::composition::CompositionInstance<
|
|
TracedInstance,
|
|
instances::result::ResultInstance<()>,
|
|
>;
|
|
|
|
#[ignore]
|
|
#[test]
|
|
fn trace_one_slice() {
|
|
let ctr: Rc<UnbalancedConstructor<TracedMonad, _>> =
|
|
UnbalancedConstructor::rc(Box::new(|node| {
|
|
Box::new(move || TracedMonad::pure(node.clone()).after_resolution())
|
|
}));
|
|
// let mut rng = rand::thread_rng();
|
|
let mut rng = rand::rngs::StdRng::seed_from_u64(426);
|
|
let big: Vec<i32> = (0..(rng.gen_range(1000..2000))).collect();
|
|
let key = big[rng.gen_range(0..big.len())];
|
|
let small: Vec<i32> = big
|
|
.iter()
|
|
.filter(|x| **x != key && rng.gen_ratio(4, 5))
|
|
.map(|x| *x)
|
|
.collect();
|
|
let t_small = ctr.from_slice(&mut rng, &small);
|
|
let t_big = ctr.from_slice(&mut rng, &big);
|
|
let traced = t_subset_of_t(
|
|
&DefaultComparator,
|
|
t_small.clone(),
|
|
t_big.clone(),
|
|
None,
|
|
None,
|
|
);
|
|
assert!(traced.value.is_ok());
|
|
// panic!("{:?}", traced.render().to_vec());
|
|
}
|
|
}
|