From 049c07ef2f08972c45de1422f48bcbe5fe2b083c Mon Sep 17 00:00:00 2001 From: ripytide Date: Wed, 23 Nov 2022 17:53:20 +0000 Subject: [PATCH] removed unit test generator for now as I want to write the implementation first --- range_bounds_set/src/bounds.rs | 32 ++----- range_bounds_set/src/btree_ext.rs | 66 ++++++++++++++ range_bounds_set/src/lib.rs | 1 + range_bounds_set/src/main.rs | 109 ----------------------- range_bounds_set/src/range_bounds_set.rs | 17 ++-- 5 files changed, 87 insertions(+), 138 deletions(-) create mode 100644 range_bounds_set/src/btree_ext.rs delete mode 100644 range_bounds_set/src/main.rs diff --git a/range_bounds_set/src/bounds.rs b/range_bounds_set/src/bounds.rs index ac8aa9b..012a5be 100644 --- a/range_bounds_set/src/bounds.rs +++ b/range_bounds_set/src/bounds.rs @@ -1,7 +1,5 @@ use std::cmp::Ordering; -use crate::range_bounds::RangeBounds; - pub enum StartBound { Included(T), Excluded(T), @@ -24,10 +22,10 @@ impl StartBound { } } - pub fn copy_outer(&self) -> StartBound<&T> { + pub fn as_ref(&self) -> StartBound<&T> { match self { - StartBound::Included(ref point) => StartBound::Included(point), - StartBound::Excluded(ref point) => StartBound::Excluded(point), + StartBound::Included(point) => StartBound::Included(point), + StartBound::Excluded(point) => StartBound::Excluded(point), StartBound::Unbounded => StartBound::Unbounded, } } @@ -120,15 +118,14 @@ impl EndBound { } } - pub fn copy_outer(&self) -> EndBound<&T> { + pub fn as_ref(&self) -> EndBound<&T> { match self { - EndBound::Included(ref point) => EndBound::Included(point), - EndBound::Excluded(ref point) => EndBound::Excluded(point), + EndBound::Included(point) => EndBound::Included(point), + EndBound::Excluded(point) => EndBound::Excluded(point), EndBound::Unbounded => EndBound::Unbounded, } } } - impl EndBound<&T> where T: Clone, @@ -182,24 +179,11 @@ where } impl From> for EndBound { - fn from(start_bound: StartBound) -> Self { - match start_bound { + fn from(end_bound: StartBound) -> Self { + match end_bound { StartBound::Included(point) => EndBound::Included(point), StartBound::Excluded(point) => EndBound::Excluded(point), StartBound::Unbounded => EndBound::Unbounded, } } } - -impl RangeBounds> - for (StartBound>, EndBound>) -where - T: Ord, -{ - fn start_bound(&self) -> StartBound<&EndBound> { - self.0.copy_outer() - } - fn end_bound(&self) -> EndBound<&EndBound> { - self.1.copy_outer() - } -} diff --git a/range_bounds_set/src/btree_ext.rs b/range_bounds_set/src/btree_ext.rs new file mode 100644 index 0000000..3a97db4 --- /dev/null +++ b/range_bounds_set/src/btree_ext.rs @@ -0,0 +1,66 @@ +use std::collections::btree_map::Range as MapRange; +use std::collections::btree_set::Range as SetRange; +use std::collections::{BTreeMap, BTreeSet}; +use std::ops::Bound; + +pub trait BTreeSetExt { + fn next_above_lower_bound(&self, lower_bound: Bound<&T>) -> Option<&T>; + fn next_below_upper_bound(&self, upper_bound: Bound<&T>) -> Option<&T>; + fn above_lower_bound(&self, lower_bound: Bound<&T>) -> SetRange; + fn above_upper_bound(&self, upper_bound: Bound<&T>) -> SetRange; +} + +impl BTreeSetExt for BTreeSet +where + T: Ord, +{ + fn next_above_lower_bound(&self, lower_bound: Bound<&T>) -> Option<&T> { + self.range((lower_bound, Bound::Unbounded)).next_back() + } + fn next_below_upper_bound(&self, upper_bound: Bound<&T>) -> Option<&T> { + self.range((Bound::Unbounded, upper_bound)).next_back() + } + fn above_lower_bound(&self, lower_bound: Bound<&T>) -> SetRange { + self.range((lower_bound, Bound::Unbounded)) + } + fn above_upper_bound(&self, upper_bound: Bound<&T>) -> SetRange { + self.range((upper_bound, Bound::Unbounded)) + } +} + +pub trait BTreeMapExt { + fn next_above_lower_bound( + &self, + lower_bound: Bound<&K>, + ) -> Option<(&K, &V)>; + fn next_below_upper_bound( + &self, + upper_bound: Bound<&K>, + ) -> Option<(&K, &V)>; + fn above_lower_bound(&self, lower_bound: Bound<&K>) -> MapRange; + fn above_upper_bound(&self, upper_bound: Bound<&K>) -> MapRange; +} + +impl BTreeMapExt for BTreeMap +where + K: Ord, +{ + fn next_above_lower_bound( + &self, + lower_bound: Bound<&K>, + ) -> Option<(&K, &V)> { + self.range((lower_bound, Bound::Unbounded)).next_back() + } + fn next_below_upper_bound( + &self, + upper_bound: Bound<&K>, + ) -> Option<(&K, &V)> { + self.range((Bound::Unbounded, upper_bound)).next_back() + } + fn above_lower_bound(&self, lower_bound: Bound<&K>) -> MapRange { + self.range((lower_bound, Bound::Unbounded)) + } + fn above_upper_bound(&self, upper_bound: Bound<&K>) -> MapRange { + self.range((upper_bound, Bound::Unbounded)) + } +} diff --git a/range_bounds_set/src/lib.rs b/range_bounds_set/src/lib.rs index 9cb213e..76830c9 100644 --- a/range_bounds_set/src/lib.rs +++ b/range_bounds_set/src/lib.rs @@ -2,6 +2,7 @@ pub mod bounds; pub mod range_bounds; pub mod range_bounds_set; +pub mod btree_ext; pub use std::ops::RangeBounds as StdRangeBounds; pub use std::ops::Bound as StdBound; diff --git a/range_bounds_set/src/main.rs b/range_bounds_set/src/main.rs deleted file mode 100644 index e9caf5c..0000000 --- a/range_bounds_set/src/main.rs +++ /dev/null @@ -1,109 +0,0 @@ -use std::ops::{Bound, Range}; - -use range_bounds_set::{range_bounds_set::RangeBoundsSet, range_bounds_ext::RangeBoundsExt}; - -static NICE_NUMBERS: &'static [u8] = &[2, 4, 6, 8, 10]; -type Sim = (Bound, Bound); - -fn main() { - println!("Hello, world!"); -} - -struct OverlapTestCase { - range_bounds_set: RangeBoundsSet, - overlap_range: Sim, -} - -struct OverlapTestCaseWithAnswer { - test_case: OverlapTestCase, - answer: Vec, -} - -fn generate_overlap_test_cases() -> Vec { - let mut output = Vec::new(); - //case zero - for overlap_range in all_sim() { - output.push(OverlapTestCase { - range_bounds_set: RangeBoundsSet::new(), - overlap_range, - }) - } - - //case one - for overlap_range in all_sim() { - for inside_range in all_sim() { - let mut range_bounds_set = RangeBoundsSet::new(); - range_bounds_set.raw_insert(inside_range); - output.push(OverlapTestCase { - range_bounds_set, - overlap_range, - }) - } - } - - //case two - - return output; -} - -fn all_valid_sim_pairs() -> Vec<(Sim, Sim)> { - let mut output = Vec::new(); - for sim1 in all_sim() { - for sim2 in all_sim() { - output.push((sim1, sim2)); - } - } - - output.retain(is_valid_sim_pair); - - return output; -} - -fn is_valid_sim_pair((sim1, sim2): &(Sim, Sim)) -> bool { - //do they overlap? - if sim1.overlaps(sim2) { - return false; - } - if - - //is it an exclusive-exclusive with start==end? -} - -fn all_sim() -> Vec { - let mut output = Vec::new(); - - //bounded-bounded - for start_bound in all_finite_bounded() { - for end_bound in all_finite_bounded() { - output.push((start_bound, end_bound)); - } - } - //bounded-unbounded - for start_bound in all_finite_bounded() { - output.push((start_bound, Bound::Unbounded)); - } - //unbounded-bounded - for end_bound in all_finite_bounded() { - output.push((Bound::Unbounded, end_bound)); - } - //bounded-bounded - output.push((Bound::Unbounded, Bound::Unbounded)); - return output; -} - -fn all_finite_bounded() -> Vec> { - let mut output = Vec::new(); - for i in 0..5 { - for k in 0..=1 { - output.push(finite_bound(i, k == 0)); - } - } - return output; -} - -fn finite_bound(x: u8, included: bool) -> Bound { - match included { - true => Bound::Included(x), - false => Bound::Excluded(x), - } -} diff --git a/range_bounds_set/src/range_bounds_set.rs b/range_bounds_set/src/range_bounds_set.rs index 5466bb6..ffb0efe 100644 --- a/range_bounds_set/src/range_bounds_set.rs +++ b/range_bounds_set/src/range_bounds_set.rs @@ -1,9 +1,10 @@ -use std::collections::{BTreeSet, HashMap, BTreeMap}; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::marker::PhantomData; use derive_new::new; use crate::bounds::{EndBound, StartBound}; +use crate::btree_ext::BTreeMapExt; use crate::range_bounds::RangeBounds; use crate::StdBound; @@ -37,13 +38,19 @@ where //we require the EndBound:Ord imlementation to work with //the Included range only StdBound::Included(range_bounds.start_bound().cloned()), - StdBound::Included(StartBound::from(range_bounds.end_bound().cloned())), + StdBound::Included(StartBound::from( + range_bounds.end_bound().cloned(), + )), ); //this range will hold all the ranges we want except possibly - //the last RangeBounds - let ends_range = self.starts.range(start_range_bounds); + //the first RangeBound in the range + let mut ends_range = self.starts.range(start_range_bounds); - let possible_missing_range_bounds = self.starts. + if let Some(possible_missing_range_bounds) = + self.starts.next_below_upper_bound(StdBound::Included( + //optimisation fix this without cloning + &range_bounds.start_bound().cloned(), + )) {} } pub fn get(&self, point: &I) {}