should probaly commit it's been a few hours lol

This commit is contained in:
ripytide 2022-11-22 07:12:24 +00:00
commit 9154cca2a5
7 changed files with 372 additions and 0 deletions

View File

@ -0,0 +1,9 @@
[package]
name = "range_bounds_set"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
derive-new = "0.5"

View File

@ -0,0 +1,23 @@
use std::ops::Bound;
pub trait BoundExt<T> {
fn inner(&self) -> Option<&T>;
fn is_unbounded(&self) -> bool;
}
impl<T> BoundExt<T> for Bound<T> {
fn inner(&self) -> Option<&T> {
match self {
Bound::Included(inner) => Some(inner),
Bound::Excluded(inner) => Some(inner),
Bound::Unbounded => None,
}
}
fn is_unbounded(&self) -> bool {
match self {
Bound::Unbounded => true,
_ => false,
}
}
}

View File

@ -0,0 +1,5 @@
#![feature(is_some_and)]
pub mod bound_ext;
pub mod range_bounds_ext;
pub mod range_bounds_set;
pub mod specific_bounds;

View File

@ -0,0 +1,109 @@
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),
}
}

View File

@ -0,0 +1,54 @@
use std::ops::{Bound, RangeBounds};
use crate::bound_ext::BoundExt;
pub trait RangeBoundsExt<T> {
fn overlaps(&self, other: &Self) -> bool;
fn get_pair(&self) -> (Bound<&T>, Bound<&T>);
}
impl<T, K> RangeBoundsExt<T> for K
where
K: RangeBounds<T>,
T: PartialOrd,
{
fn get_pair(&self) -> (Bound<&T>, Bound<&T>) {
(self.start_bound(), self.end_bound())
}
fn overlaps(&self, other: &Self) -> bool {
let self_start_contained = self
.start_bound()
.inner()
.is_some_and(|start| other.contains(*start));
let self_end_contained = self
.end_bound()
.inner()
.is_some_and(|end| other.contains(*end));
let other_start_contained = other
.start_bound()
.inner()
.is_some_and(|start| self.contains(*start));
let other_end_contained = other
.end_bound()
.inner()
.is_some_and(|end| self.contains(*end));
let double_unbounded = self.start_bound().is_unbounded()
&& self.end_bound().is_unbounded()
&& other.start_bound().is_unbounded()
&& other.end_bound().is_unbounded();
let same_exclusive = match (self.get_pair(), other.get_pair()) {
(
(Bound::Excluded(start1), Bound::Excluded(end1)),
(Bound::Excluded(start2), Bound::Excluded(end2)),
) if start1 == start2 && end1 == end2 => true,
_ => false,
};
self_start_contained
|| self_end_contained
|| other_start_contained
|| other_end_contained
|| double_unbounded
|| same_exclusive
}
}

View File

@ -0,0 +1,69 @@
use std::collections::{BTreeSet, HashMap};
use std::marker::PhantomData;
use std::ops::{Bound, RangeBounds};
use derive_new::new;
use crate::bound_ext::{EndBoundWithOrd, StartBoundWithOrd};
type Id = u128;
//todo switch to slot map thingy
#[derive(Default, new)]
pub struct RangeBoundsSet<T, I> {
#[new(default)]
ranges: HashMap<Id, T>,
#[new(default)]
starts: BTreeSet<StartBoundWithOrd<I>>,
#[new(default)]
ends: BTreeSet<EndBoundWithOrd<I>>,
phantom_data: PhantomData<I>,
#[new(default)]
id: u128,
}
impl<T, I> RangeBoundsSet<T, I>
where
T: RangeBounds<I>,
I: Ord,
{
//returns Err(()) if the inserting the given range overlaps another range
//coalesces ranges if they touch
pub fn insert(&mut self, range: T) -> Result<(), ()> {
Ok(())
}
pub fn raw_insert(&mut self, range: T) {}
pub fn overlapping(&self, range: T) {
self.ends.range(range);
}
pub fn get(&self, point: &I) {}
}
#[cfg(test)]
mod tests {
//use pretty_assertions::assert_eq;
use super::*;
// So there are a lot of permutations for overlaps checks: like 100's even
// for less than 3 ranges inside the see my picture in
// notes/ for an idea
// Hence the strategy since I want thorough testing at least for
// T = { 0, 1, 2 } where T is the number of ranges in the rangeset
// upon query, and I want every valid (maintains invariant of no
// overlaps (only relevant for T=2)) permutation of query to
// interval set to have it's own test.
//
// This strategy is open-ended if anyone feels like manually
// inputing the T=3 cases ;p
//
// And so rather than figuring all the valid cases manually I
// wrote a script to do it for me, and then I also wrote a helper
// script to streamline the manual input process. The script
// essentially enumerates all of the generated cases and asks me
// to input the expected
}

View File

@ -0,0 +1,103 @@
use std::cmp::Ordering;
use crate::bound_ext::BoundExt;
pub enum StartBound<T> {
Included(T),
Excluded(T),
Unbounded,
}
impl<T> PartialEq for StartBound<T>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
match (self.inner(), other.inner()) {
(Some(start1), Some(start2)) => start1 == start2,
(None, None) => true,
_ => false,
}
}
}
impl<T> PartialOrd for StartBound<T>
where
T: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (self.inner(), other.inner()) {
(Some(start1), Some(start2)) => start1.partial_cmp(start2),
(None, Some(_)) => Some(Ordering::Less),
(Some(_), None) => Some(Ordering::Greater),
(None, None) => Some(Ordering::Equal),
}
}
}
impl<T> BoundExt<T> for StartBound<T> {
fn inner(&self) -> Option<&T> {
match self {
StartBound::Included(inner) => Some(inner),
StartBound::Excluded(inner) => Some(inner),
StartBound::Unbounded => None,
}
}
fn is_unbounded(&self) -> bool {
match self {
StartBound::Unbounded => true,
_ => false,
}
}
}
pub enum EndBound<T> {
Included(T),
Excluded(T),
Unbounded,
}
impl<T> PartialEq for EndBound<T>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
match (self.inner(), other.inner()) {
(Some(start1), Some(start2)) => start1 == start2,
(None, None) => true,
_ => false,
}
}
}
impl<T> PartialOrd for EndBound<T>
where
T: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (self.inner(), other.inner()) {
(Some(start1), Some(start2)) => start1.partial_cmp(start2),
(None, Some(_)) => Some(Ordering::Less),
(Some(_), None) => Some(Ordering::Greater),
(None, None) => Some(Ordering::Equal),
}
}
}
impl<T> BoundExt<T> for EndBound<T> {
fn inner(&self) -> Option<&T> {
match self {
EndBound::Included(inner) => Some(inner),
EndBound::Excluded(inner) => Some(inner),
EndBound::Unbounded => None,
}
}
fn is_unbounded(&self) -> bool {
match self {
EndBound::Unbounded => true,
_ => false,
}
}
}