removed unit test generator for now as I want to write the implementation first
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use crate::range_bounds::RangeBounds;
|
||||
|
||||
pub enum StartBound<T> {
|
||||
Included(T),
|
||||
Excluded(T),
|
||||
@@ -24,10 +22,10 @@ impl<T> StartBound<T> {
|
||||
}
|
||||
}
|
||||
|
||||
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<T> EndBound<T> {
|
||||
}
|
||||
}
|
||||
|
||||
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<T> EndBound<&T>
|
||||
where
|
||||
T: Clone,
|
||||
@@ -182,24 +179,11 @@ where
|
||||
}
|
||||
|
||||
impl<T> From<StartBound<T>> for EndBound<T> {
|
||||
fn from(start_bound: StartBound<T>) -> Self {
|
||||
match start_bound {
|
||||
fn from(end_bound: StartBound<T>) -> Self {
|
||||
match end_bound {
|
||||
StartBound::Included(point) => EndBound::Included(point),
|
||||
StartBound::Excluded(point) => EndBound::Excluded(point),
|
||||
StartBound::Unbounded => EndBound::Unbounded,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RangeBounds<EndBound<T>>
|
||||
for (StartBound<EndBound<T>>, EndBound<EndBound<T>>)
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
fn start_bound(&self) -> StartBound<&EndBound<T>> {
|
||||
self.0.copy_outer()
|
||||
}
|
||||
fn end_bound(&self) -> EndBound<&EndBound<T>> {
|
||||
self.1.copy_outer()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
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<T>;
|
||||
fn above_upper_bound(&self, upper_bound: Bound<&T>) -> SetRange<T>;
|
||||
}
|
||||
|
||||
impl<T> BTreeSetExt<T> for BTreeSet<T>
|
||||
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<T> {
|
||||
self.range((lower_bound, Bound::Unbounded))
|
||||
}
|
||||
fn above_upper_bound(&self, upper_bound: Bound<&T>) -> SetRange<T> {
|
||||
self.range((upper_bound, Bound::Unbounded))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BTreeMapExt<K, V> {
|
||||
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<K, V>;
|
||||
fn above_upper_bound(&self, upper_bound: Bound<&K>) -> MapRange<K, V>;
|
||||
}
|
||||
|
||||
impl<K, V> BTreeMapExt<K, V> for BTreeMap<K, V>
|
||||
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<K, V> {
|
||||
self.range((lower_bound, Bound::Unbounded))
|
||||
}
|
||||
fn above_upper_bound(&self, upper_bound: Bound<&K>) -> MapRange<K, V> {
|
||||
self.range((upper_bound, Bound::Unbounded))
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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<u8>, Bound<u8>);
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
|
||||
struct OverlapTestCase {
|
||||
range_bounds_set: RangeBoundsSet<Sim, u8>,
|
||||
overlap_range: Sim,
|
||||
}
|
||||
|
||||
struct OverlapTestCaseWithAnswer {
|
||||
test_case: OverlapTestCase,
|
||||
answer: Vec<Sim>,
|
||||
}
|
||||
|
||||
fn generate_overlap_test_cases() -> Vec<OverlapTestCase> {
|
||||
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<Sim> {
|
||||
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<Bound<u8>> {
|
||||
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<u8> {
|
||||
match included {
|
||||
true => Bound::Included(x),
|
||||
false => Bound::Excluded(x),
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
|
||||
Reference in New Issue
Block a user