//! 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>, cr: Rc>, key: Rc, } pub type UnbalancedResolution<'a, T, A> = Wrap<'a, Rc>, T>; pub struct UnbalancedReference<'a, T: Monad<'a>, A: 'a>( Box UnbalancedResolution<'a, T, A>>, ); pub enum UnbalancedTree<'a, T: Monad<'a>, A: 'a> { Leaf, Node(Rc>), } 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) -> Rc> { 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>, T> { ::fmap( |rc| rc as Rc>, self.0(), ) } 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>> { match self { UnbalancedTree::Leaf => None, UnbalancedTree::Node(reference) => Some(reference.clone()), } } } type WrapType<'a, T, A> = Box< dyn 'a + Fn(Rc>) -> Box 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 { wrap }.into() } pub fn leaf(&self) -> Rc> { UnbalancedTree::Leaf.into() } pub fn node( self: &Rc, cl: Rc>, key: A, cr: Rc>, ) -> Rc> { 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( self: &Rc, rng: &mut R, slice: &[A], ) -> Rc> 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::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::rc(Box::new(|node| Box::new(move || Ok(node.clone())))); let mut rng = rand::thread_rng(); for _ in 0..1000 { let big: Vec = (0..(rng.gen_range(2..10))).collect(); let key = big[rng.gen_range(0..big.len())]; let small: Vec = 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::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 = (0..(rng.gen_range(1000..2000))).collect(); let key = big[rng.gen_range(0..big.len())]; let small: Vec = 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()); } }