Compare commits

..

2 Commits

Author SHA1 Message Date
3f6d290f5c unbalanced tree 2023-04-25 17:40:04 +00:00
9ef14b53ac fix subset check 2023-04-25 17:39:25 +00:00
5 changed files with 276 additions and 11 deletions

View File

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

View File

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

View File

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

View File

@ -0,0 +1,258 @@
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,11 +306,13 @@ mod stackless_test {
}
}
#[ignore]
#[test]
fn test_factorial() {
assert_eq!(factorial(10).evaluate(), 3628800);
}
#[ignore]
#[test]
fn test_dumb() {
let n = 1000;