Compare commits

..

No commits in common. "3f6d290f5c61e60139b62befdf933e2785e8d6a0" and "5d604d283475c7a7fc4c093f13d9d6c0d9390cb9" have entirely different histories.

5 changed files with 11 additions and 276 deletions

View File

@ -1,3 +1 @@
{ {}
"rust-analyzer.showUnlinkedFileNotification": false
}

View File

@ -18,4 +18,3 @@ radn-derive = { path = "radn-derive" }
[dev-dependencies] [dev-dependencies]
sha2 = "0.10.6" sha2 = "0.10.6"
rand = "0.8.5"

View File

@ -1,7 +1,5 @@
//! Traversible binary trees. //! Traversible binary trees.
pub mod unbalanced;
use std::rc::Rc; use std::rc::Rc;
use crate::func::*; use crate::func::*;
@ -52,24 +50,24 @@ pub type Split<'a, T, A, D> = (
Rc<A>, Rc<A>,
); );
pub trait TraversibleBinaryNode<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>: 'a { pub trait TraversibleBinaryNode<'a, T: Monad, A, D: 'a + PartialEq>: 'a {
fn split(&self) -> Split<'a, T, A, D>; fn split(&self) -> Split<'a, T, A, D>;
fn to_tree(self: Rc<Self>) -> Rc<dyn TraversibleBinaryTree<'a, T, A, D>>; fn to_tree(self: Rc<Self>) -> Rc<dyn TraversibleBinaryTree<'a, T, A, D>>;
} }
pub trait TraversibleBinaryReference<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>: 'a { pub trait TraversibleBinaryReference<'a, T: Monad, A, D: 'a + PartialEq>: 'a {
fn resolve(&self) -> <T as WeakFunctor>::F<'a, Rc<dyn TraversibleBinaryNode<'a, T, A, D>>>; fn resolve(&self) -> <T as WeakFunctor>::F<'a, Rc<dyn TraversibleBinaryNode<'a, T, A, D>>>;
/// This should be enough to compare reference for equality. /// This should be enough to compare reference for equality.
fn data(&self) -> D; fn data(&self) -> D;
} }
pub trait TraversibleBinaryTree<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>: 'a { pub trait TraversibleBinaryTree<'a, T: Monad, A, D: 'a + PartialEq>: 'a {
fn refer(&self) -> Option<Rc<dyn TraversibleBinaryReference<'a, T, A, D>>>; fn refer(&self) -> Option<Rc<dyn TraversibleBinaryReference<'a, T, A, D>>>;
} }
pub fn n_contains<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>( pub fn n_contains<'a, T: Monad, A, D: 'a + PartialEq>(
comparator: &'a dyn Comparator<A>, comparator: &'a dyn Comparator<A>,
n_set: Rc<dyn TraversibleBinaryNode<'a, T, A, D>>, n_set: Rc<dyn TraversibleBinaryNode<'a, T, A, D>>,
key: Rc<A>, key: Rc<A>,
@ -82,7 +80,7 @@ pub fn n_contains<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>(
} }
} }
pub fn r_contains<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>( pub fn r_contains<'a, T: Monad, A, D: 'a + PartialEq>(
comparator: &'a dyn Comparator<A>, comparator: &'a dyn Comparator<A>,
r_set: Rc<dyn TraversibleBinaryReference<'a, T, A, D>>, r_set: Rc<dyn TraversibleBinaryReference<'a, T, A, D>>,
key: Rc<A>, key: Rc<A>,
@ -90,7 +88,7 @@ pub fn r_contains<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>(
T::bind(r_set.resolve(), |n_set| n_contains(comparator, n_set, key)) T::bind(r_set.resolve(), |n_set| n_contains(comparator, n_set, key))
} }
pub fn t_contains<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>( pub fn t_contains<'a, T: Monad, A, D: 'a + PartialEq>(
comparator: &'a dyn Comparator<A>, comparator: &'a dyn Comparator<A>,
t_set: Rc<dyn TraversibleBinaryTree<'a, T, A, D>>, t_set: Rc<dyn TraversibleBinaryTree<'a, T, A, D>>,
key: Rc<A>, key: Rc<A>,
@ -101,7 +99,7 @@ pub fn t_contains<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>(
} }
} }
pub fn n_subset_of_n<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>( pub fn n_subset_of_n<'a, T: Monad, A, D: 'a + PartialEq>(
comparator: &'a dyn Comparator<A>, comparator: &'a dyn Comparator<A>,
n_subset: Rc<dyn TraversibleBinaryNode<'a, T, A, D>>, n_subset: Rc<dyn TraversibleBinaryNode<'a, T, A, D>>,
n_superset: Rc<dyn TraversibleBinaryNode<'a, T, A, D>>, n_superset: Rc<dyn TraversibleBinaryNode<'a, T, A, D>>,
@ -130,7 +128,7 @@ pub fn n_subset_of_n<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>(
t_subset_of_t( t_subset_of_t(
comparator, comparator,
t_subr, t_subr,
n_superset.to_tree(), n_subset.to_tree(),
Some(k_sub.clone()), Some(k_sub.clone()),
k_r, k_r,
), ),
@ -149,7 +147,7 @@ pub fn n_subset_of_n<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>(
t_subset_of_t( t_subset_of_t(
comparator, comparator,
t_subl, t_subl,
n_superset.to_tree(), n_subset.to_tree(),
k_l, k_l,
Some(k_sub.clone()), Some(k_sub.clone()),
), ),
@ -159,7 +157,7 @@ pub fn n_subset_of_n<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>(
} }
} }
pub fn r_subset_of_r<'a, T: 'a + Monad, A: 'a, D: 'a + PartialEq>( pub fn r_subset_of_r<'a, T: Monad, A, D: 'a + PartialEq>(
comparator: &'a dyn Comparator<A>, comparator: &'a dyn Comparator<A>,
r_subset: Rc<dyn TraversibleBinaryReference<'a, T, A, D>>, r_subset: Rc<dyn TraversibleBinaryReference<'a, T, A, D>>,
r_superset: Rc<dyn TraversibleBinaryReference<'a, T, A, D>>, r_superset: Rc<dyn TraversibleBinaryReference<'a, T, A, D>>,

View File

@ -1,258 +0,0 @@
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: 'a + Monad, A: 'a> {
cl: Rc<UnbalancedTree<'a, T, A>>,
cr: Rc<UnbalancedTree<'a, T, A>>,
key: Rc<A>,
}
pub type UnbalancedResolution<'a, T, A> = <T as WeakFunctor>::F<'a, Rc<UnbalancedNode<'a, T, A>>>;
pub struct UnbalancedReference<'a, T: 'a + Monad, A: 'a>(
Box<dyn 'a + Fn() -> UnbalancedResolution<'a, T, A>>,
);
pub enum UnbalancedTree<'a, T: 'a + Monad, A: 'a> {
Leaf,
Node(Rc<UnbalancedReference<'a, T, A>>),
}
impl<'a, A: 'a + Display> Display for UnbalancedNode<'a, classes::solo::SoloClass, A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("({} {} {})", self.cl, self.key, self.cr))
}
}
impl<'a, A: 'a + Display> Display for UnbalancedReference<'a, classes::solo::SoloClass, 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 UnbalancedTree<'a, classes::solo::SoloClass, A> {
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, T: 'a + Monad, 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: 'a + Monad, A: 'a> TraversibleBinaryReference<'a, T, A, UnbalancedData>
for UnbalancedReference<'a, T, A>
{
fn resolve(
&self,
) -> <T as WeakFunctor>::F<'a, Rc<dyn TraversibleBinaryNode<'a, T, A, UnbalancedData>>> {
<T as Functor>::fmap(
|rc| rc as Rc<dyn TraversibleBinaryNode<'a, T, A, UnbalancedData>>,
self.0(),
)
}
fn data(&self) -> UnbalancedData {
UnbalancedData
}
}
impl<'a, T: 'a + Monad, 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>>) -> UnbalancedResolution<'a, T, A>>;
pub struct UnbalancedConstructor<'a, T: 'a + Monad, A: 'a> {
wrap: WrapType<'a, T, A>,
}
impl<'a, T: 'a + Monad, 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(Box::new(move || {
(ctr.wrap)(node.clone())
}))))
.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;
use super::*;
#[test]
fn test_simple_slices() {
let ctr: Rc<UnbalancedConstructor<classes::solo::SoloClass, _>> =
UnbalancedConstructor::rc(Box::new(|node| node));
let mut rng = rand::thread_rng();
let t_set = ctr.from_slice(&mut rng, &[0]);
assert!(t_contains(&DefaultComparator, t_set.clone(), 0.into()));
assert!(!t_contains(&DefaultComparator, t_set.clone(), 1.into()));
assert!(t_subset_of_t(
&DefaultComparator,
t_set.clone(),
t_set.clone(),
None,
None
));
assert!(!t_subset_of_t(
&DefaultComparator,
t_set.clone(),
ctr.leaf(),
None,
None
));
assert!(t_subset_of_t(
&DefaultComparator,
ctr.leaf(),
t_set.clone(),
None,
None
));
assert!(t_subset_of_t(
&DefaultComparator,
ctr.leaf(),
ctr.leaf(),
None,
None
));
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
));
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
));
}
#[test]
fn test_random_slices() {
let ctr: Rc<UnbalancedConstructor<classes::solo::SoloClass, _>> =
UnbalancedConstructor::rc(Box::new(|node| node));
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
),
"{} should be a subset of {}",
t_small,
t_big,
);
assert!(
!t_subset_of_t(
&DefaultComparator,
t_big.clone(),
t_small.clone(),
None,
None
),
"{} should not be a subset of {}",
t_big,
t_small,
);
}
}
}

View File

@ -306,13 +306,11 @@ mod stackless_test {
} }
} }
#[ignore]
#[test] #[test]
fn test_factorial() { fn test_factorial() {
assert_eq!(factorial(10).evaluate(), 3628800); assert_eq!(factorial(10).evaluate(), 3628800);
} }
#[ignore]
#[test] #[test]
fn test_dumb() { fn test_dumb() {
let n = 1000; let n = 1000;