radn-rs/src/flow/traversible/unbalanced.rs
2023-05-30 00:09:38 +00:00

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());
}
}