From c1f48b1c083be5adf51d5f63db71ba5db7c02563 Mon Sep 17 00:00:00 2001 From: timofey Date: Sat, 17 Jun 2023 03:53:40 +0000 Subject: [PATCH] `AvlTrees` --- src/flow/binary/balancing.rs | 1 + src/rstd/collections/avl.rs | 30 ++++++------ src/rstd/collections/avl/binary.rs | 13 +++--- src/rstd/collections/avl/context.rs | 71 +++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 23 deletions(-) create mode 100644 src/rstd/collections/avl/context.rs diff --git a/src/flow/binary/balancing.rs b/src/flow/binary/balancing.rs index 721dc5b..9fd1711 100644 --- a/src/flow/binary/balancing.rs +++ b/src/flow/binary/balancing.rs @@ -37,6 +37,7 @@ impl<'a, BT: FunctorContext<'a>> FunctorContext<'a> for BalancedTrees { type T = BT::T; } +#[derive(Debug)] pub enum BalancingError { LeafHeight(u64), NodeHeight, diff --git a/src/rstd/collections/avl.rs b/src/rstd/collections/avl.rs index e0b6d13..bfa877c 100644 --- a/src/rstd/collections/avl.rs +++ b/src/rstd/collections/avl.rs @@ -1,7 +1,9 @@ pub mod binary; +pub mod context; use std::{error::Error, fmt::Display, rc::Rc}; +use crate::flow::binary::balancing::*; use crate::rcore::*; use crate::rstd::{ atomic::{au64::*, *}, @@ -14,11 +16,7 @@ pub enum AvlError { Int(IntParseError), Point(PointParseError), Key(E), - LeafHeight(u64), - NodeHeight, - Balance(u64, u64), - HeightOverflow, - HeightMismatch { child: (u64, u64), parent: u64 }, + Balancing(BalancingError), } impl From for AvlError { @@ -33,6 +31,12 @@ impl From for AvlError { } } +impl From for AvlError { + fn from(value: BalancingError) -> Self { + Self::Balancing(value) + } +} + impl Display for AvlError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -45,14 +49,8 @@ impl Display for AvlError { Self::Key(key_error) => { write!(f, "failed to parse AVL node key: {key_error}") } - Self::NodeHeight => write!(f, "invalid AVL non-leaf height: 0."), - Self::LeafHeight(height) => { - write!(f, "invalid AVL leaf height: {height}!=0.") - } - Self::Balance(hl, hr) => write!(f, "unbalanced AVL node: {hl} {hr}."), - Self::HeightOverflow => write!(f, "AVL tree height overflow"), - Self::HeightMismatch { child, parent } => { - write!(f, "AVL child-parent height mismatch: {child:?}, {parent}") + Self::Balancing(balancing) => { + write!(f, "balancing: {balancing}") } } } @@ -120,7 +118,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Avl fn balanced(hl: u64, hr: u64) -> Result<(), AvlError> { if std::cmp::max(hl, hr) - std::cmp::min(hl, hr) > 1 { - return Err(AvlError::Balance(hl, hr)); + Err(BalancingError::Balance(hl, hr))? } Ok(()) } @@ -175,10 +173,10 @@ impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> Factory<'a, Ctx> for AvlTreeFact let height = u64::a_deserialize(deserializer)?; if let Nullable::Null(_) = node { if height != 0 { - return Err(AvlError::LeafHeight(height)); + Err(BalancingError::LeafHeight(height))? } } else if height == 0 { - return Err(AvlError::NodeHeight); + Err(BalancingError::NodeHeight)? } Ok(AvlTree { node, height }) } diff --git a/src/rstd/collections/avl/binary.rs b/src/rstd/collections/avl/binary.rs index 19ea17a..265960c 100644 --- a/src/rstd/collections/avl/binary.rs +++ b/src/rstd/collections/avl/binary.rs @@ -23,7 +23,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> AvlNode<'a, Ctx, A> { fn parent_height(&self) -> AvlResult<'a, Ctx, A, u64> { std::cmp::max(self.l.height, self.r.height) .checked_add(1) - .ok_or(AvlError::HeightOverflow) + .ok_or(AvlError::Balancing(BalancingError::HeightOverflow)) } pub fn into_tree(self) -> AvlTreeResult<'a, Ctx, A> { @@ -43,14 +43,13 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> AvlNode<'a, Ctx, A> { fn matches_height(&self, parent_height: u64) -> AvlResult<'a, Ctx, A, ()> { let expected = self.parent_height()?; - if expected == parent_height { - Ok(()) - } else { - Err(AvlError::HeightMismatch { - child: (self.l.height, self.r.height), + if expected != parent_height { + Err(BalancingError::HeightMismatch { + children: (self.l.height, self.r.height), parent: parent_height, - }) + })? } + Ok(()) } } diff --git a/src/rstd/collections/avl/context.rs b/src/rstd/collections/avl/context.rs new file mode 100644 index 0000000..db94f6e --- /dev/null +++ b/src/rstd/collections/avl/context.rs @@ -0,0 +1,71 @@ +use std::marker::PhantomData; + +use crate::{ + flow::{binary::*, comparator::*}, + func::context::*, + rstd::fallible::*, +}; + +use super::{binary::*, *}; + +struct AvlTrees(Rc, PhantomData); + +impl AvlTrees { + fn new(comparator: Rc) -> Self { + Self(comparator, PhantomData) + } +} + +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone, C: 'a + Comparator> Clone + for AvlTrees +{ + fn clone(&self) -> Self { + Self::new(self.0.clone()) + } +} + +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone, C: 'a + Comparator> + FunctorContext<'a> for AvlTrees +{ + type T = FallibleMonad< + 'a, + Ctx, + ResolutionError>>>, + >; +} + +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone, C: 'a + Comparator> BinaryTrees<'a> + for AvlTrees +{ + type Node = AvlNode<'a, Ctx, A>; + + type Reference = AvlReference<'a, Ctx, A>; + + type Tree = AvlTree<'a, Ctx, A>; + + type Key = A; + + type Comparator = C; + + type _Tm = Self::T; + + fn comparator(&self) -> &Self::Comparator { + &self.0 + } + + fn split(&self, node: &Self::Node) -> Split<'a, Self> { + (node.l.clone(), node.r.clone(), node.key.clone()) + } + + fn resolve(&self, reference: &Self::Reference) -> BTWrap<'a, Self, Self::Node> { + Self::fmap(Ctx::stuff(reference.resolve()), |rc| rc.as_ref().clone()) + } + + fn equal(&self, rl: &Self::Reference, rr: &Self::Reference) -> bool { + rl == rr + } + + fn refer(&self, tree: &Self::Tree) -> Option { + tree.reference() + } +}