Skip to content

Commit

Permalink
Change method (Add|Delete)(Range) to be functions
Browse files Browse the repository at this point in the history
  • Loading branch information
b97tsk committed Jan 23, 2024
1 parent 487bbe8 commit 04a60b3
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 72 deletions.
6 changes: 3 additions & 3 deletions difference_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ func TestDifference(t *testing.T) {
var x2, x3, x5 Set[E]

for i := 2; i < 32; i += 2 {
x2.Add(One(E(i)))
x2 = Add(x2, One(E(i)))
}

for i := 3; i < 32; i += 3 {
x3.Add(One(E(i)))
x3 = Add(x3, One(E(i)))
}

for i := 5; i < 32; i += 5 {
x5.Add(One(E(i)))
x5 = Add(x5, One(E(i)))
}

return Difference(x2, x3, x5)
Expand Down
4 changes: 2 additions & 2 deletions fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func FuzzAdd(f *testing.F) {
z := append(Set[elems.Uint8](nil), x...)

for _, r := range y {
z.Add(r)
z = Add(z, r)
}

if w := plainUnion(x, y); !z.Equal(w) {
Expand All @@ -32,7 +32,7 @@ func FuzzDelete(f *testing.F) {
z := append(Set[elems.Uint8](nil), x...)

for _, r := range y {
z.Delete(r)
z = Delete(z, r)
}

if w := plainDifference(x, y); !z.Equal(w) {
Expand Down
6 changes: 3 additions & 3 deletions intersection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ func TestIntersection(t *testing.T) {
var x2, x3, x5 Set[E]

for i := 2; i < 100; i += 2 {
x2.Add(One(E(i)))
x2 = Add(x2, One(E(i)))
}

for i := 3; i < 100; i += 3 {
x3.Add(One(E(i)))
x3 = Add(x3, One(E(i)))
}

for i := 5; i < 100; i += 5 {
x5.Add(One(E(i)))
x5 = Add(x5, One(E(i)))
}

return Intersection(x2, x3, x5)
Expand Down
66 changes: 30 additions & 36 deletions intervalset.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,24 +96,22 @@ func CollectInto[E Elem[E]](x Set[E], s ...Interval[E]) Set[E] {
r1.High = r.High
}
default:
x.Add(r)
x = Add(x, r)
}
}

return x
}

// Add adds range [r.Low, r.High) into x.
func (x *Set[E]) Add(r Interval[E]) {
x.AddRange(r.Low, r.High)
// Add adds range [r.Low, r.High) into x, returning the modified Set.
func Add[E Elem[E]](x Set[E], r Interval[E]) Set[E] {
return AddRange(x, r.Low, r.High)
}

// AddRange adds range [lo, hi) into x.
func (x *Set[E]) AddRange(lo, hi E) {
s := *x

i := sort.Search(len(s), func(i int) bool { return s[i].Low.Compare(lo) > 0 })
// j := sort.Search(len(s), func(i int) bool { return s[i].High.Compare(hi) > 0 })
// AddRange adds range [lo, hi) into x, returning the modified Set.
func AddRange[E Elem[E]](x Set[E], lo, hi E) Set[E] {
i := sort.Search(len(x), func(i int) bool { return x[i].Low.Compare(lo) > 0 })
// j := sort.Search(len(x), func(i int) bool { return x[i].High.Compare(hi) > 0 })

// ┌────────┬─────────────────────────────────────────┐
// │ │ j-1 j i-1 i │
Expand Down Expand Up @@ -142,50 +140,47 @@ func (x *Set[E]) AddRange(lo, hi E) {

// Optimized: j >= i-1.
off := max(0, i-1)
t := s[off:]
j := off + sort.Search(len(t), func(i int) bool { return t[i].High.Compare(hi) > 0 })
z := x[off:]
j := off + sort.Search(len(z), func(i int) bool { return z[i].High.Compare(hi) > 0 })

if i > j { // Case 1 and 2.
return
return x
}

// Case 3, 4 and 5.

if i > 0 {
if r := &s[i-1]; r.High.Compare(lo) >= 0 {
if r := &x[i-1]; r.High.Compare(lo) >= 0 {
lo = r.Low
i--
}
}

if j < len(s) {
if r := &s[j]; r.Low.Compare(hi) <= 0 {
if j < len(x) {
if r := &x[j]; r.Low.Compare(hi) <= 0 {
hi = r.High
j++
}
}

if i == j { // Case 3 (where lo and hi overlap).
if lo.Compare(hi) >= 0 { // Get rid of the devil first.
return
return x
}
}

s = slices.Replace(s, i, j, Range(lo, hi))
*x = s
return slices.Replace(x, i, j, Range(lo, hi))
}

// Delete removes range [r.Low, r.High) from x.
func (x *Set[E]) Delete(r Interval[E]) {
x.DeleteRange(r.Low, r.High)
// Delete removes range [r.Low, r.High) from x, returning the modified Set.
func Delete[E Elem[E]](x Set[E], r Interval[E]) Set[E] {
return DeleteRange(x, r.Low, r.High)
}

// DeleteRange removes range [lo, hi) from x.
func (x *Set[E]) DeleteRange(lo, hi E) {
s := *x

i := sort.Search(len(s), func(i int) bool { return s[i].High.Compare(lo) > 0 })
// j := sort.Search(len(s), func(i int) bool { return s[i].Low.Compare(hi) > 0 })
// DeleteRange removes range [lo, hi) from x, returning the modified Set.
func DeleteRange[E Elem[E]](x Set[E], lo, hi E) Set[E] {
i := sort.Search(len(x), func(i int) bool { return x[i].High.Compare(lo) > 0 })
// j := sort.Search(len(x), func(i int) bool { return x[i].Low.Compare(hi) > 0 })

// ┌────────┬─────────────────────────────────────────┐
// │ │ j-1 j i-1 i │
Expand Down Expand Up @@ -213,33 +208,32 @@ func (x *Set[E]) DeleteRange(lo, hi E) {
// └────────┴─────────────────────────────────────────┘

// Optimized: j >= i.
t := s[i:]
j := i + sort.Search(len(t), func(i int) bool { return t[i].Low.Compare(hi) > 0 })
z := x[i:]
j := i + sort.Search(len(z), func(i int) bool { return z[i].Low.Compare(hi) > 0 })

if i == j { // Case 1, 2 and 3.
return
return x
}

if i == j-1 { // Case 4.
if lo.Compare(hi) >= 0 { // Get rid of the devil first.
return
return x
}
}

// Case 4 and 5.

v := make([]Interval[E], 0, 2)

if r := &s[i]; r.Low.Compare(lo) < 0 {
if r := &x[i]; r.Low.Compare(lo) < 0 {
v = append(v, Range(r.Low, lo))
}

if r := &s[j-1]; r.High.Compare(hi) > 0 {
if r := &x[j-1]; r.High.Compare(hi) > 0 {
v = append(v, Range(hi, r.High))
}

s = slices.Replace(s, i, j, v...)
*x = s
return slices.Replace(x, i, j, v...)
}

// Contains reports whether x contains every element in range [r.Low, r.High).
Expand Down
34 changes: 12 additions & 22 deletions intervalset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,36 +58,31 @@ func TestCreation(t *testing.T) {
func TestAdd(t *testing.T) {
type E = elems.Int

add := func(s Set[E], r Interval[E]) Set[E] {
s.Add(r)
return s
}

testCases := []struct {
Actual, Expected Set[E]
}{
{
add(Set[E]{{1, 5}, {11, 15}}, Range[E](5, 11)),
Add(Set[E]{{1, 5}, {11, 15}}, Range[E](5, 11)),
Set[E]{{1, 15}},
},
{
add(Set[E]{{1, 5}, {11, 15}}, Range[E](5, 9)),
Add(Set[E]{{1, 5}, {11, 15}}, Range[E](5, 9)),
Set[E]{{1, 9}, {11, 15}},
},
{
add(Set[E]{{1, 5}, {11, 15}}, Range[E](7, 11)),
Add(Set[E]{{1, 5}, {11, 15}}, Range[E](7, 11)),
Set[E]{{1, 5}, {7, 15}},
},
{
add(Set[E]{{1, 5}, {11, 15}}, Range[E](7, 9)),
Add(Set[E]{{1, 5}, {11, 15}}, Range[E](7, 9)),
Set[E]{{1, 5}, {7, 9}, {11, 15}},
},
{
add(Set[E]{{1, 5}, {11, 15}}, Range[E](9, 7)),
Add(Set[E]{{1, 5}, {11, 15}}, Range[E](9, 7)),
Set[E]{{1, 5}, {11, 15}},
},
{
add(Set[E]{{1, 5}, {11, 15}}, Range[E](15, 11)),
Add(Set[E]{{1, 5}, {11, 15}}, Range[E](15, 11)),
Set[E]{{1, 5}, {11, 15}},
},
}
Expand All @@ -103,36 +98,31 @@ func TestAdd(t *testing.T) {
func TestDelete(t *testing.T) {
type E = elems.Int

del := func(s Set[E], r Interval[E]) Set[E] {
s.Delete(r)
return s
}

testCases := []struct {
Actual, Expected Set[E]
}{
{
del(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](5, 11)),
Delete(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](5, 11)),
Set[E]{{1, 3}, {13, 15}},
},
{
del(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](5, 9)),
Delete(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](5, 9)),
Set[E]{{1, 3}, {9, 11}, {13, 15}},
},
{
del(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](7, 11)),
Delete(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](7, 11)),
Set[E]{{1, 3}, {5, 7}, {13, 15}},
},
{
del(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](7, 9)),
Delete(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](7, 9)),
Set[E]{{1, 3}, {5, 7}, {9, 11}, {13, 15}},
},
{
del(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](9, 7)),
Delete(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](9, 7)),
Set[E]{{1, 3}, {5, 11}, {13, 15}},
},
{
del(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](5, 3)),
Delete(Set[E]{{1, 3}, {5, 11}, {13, 15}}, Range[E](5, 3)),
Set[E]{{1, 3}, {5, 11}, {13, 15}},
},
}
Expand Down
6 changes: 3 additions & 3 deletions symdiff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ func TestSymmetricDifference(t *testing.T) {
var x2, x3, x5 Set[E]

for i := 2; i < 32; i += 2 {
x2.Add(One(E(i)))
x2 = Add(x2, One(E(i)))
}

for i := 3; i < 32; i += 3 {
x3.Add(One(E(i)))
x3 = Add(x3, One(E(i)))
}

for i := 5; i < 32; i += 5 {
x5.Add(One(E(i)))
x5 = Add(x5, One(E(i)))
}

return SymmetricDifference(x2, x3, x5)
Expand Down
6 changes: 3 additions & 3 deletions union_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ func TestUnion(t *testing.T) {
var x2, x3, x5 Set[E]

for i := 2; i < 32; i += 2 {
x2.Add(One(E(i)))
x2 = Add(x2, One(E(i)))
}

for i := 3; i < 32; i += 3 {
x3.Add(One(E(i)))
x3 = Add(x3, One(E(i)))
}

for i := 5; i < 32; i += 5 {
x5.Add(One(E(i)))
x5 = Add(x5, One(E(i)))
}

return Union(x2, x3, x5)
Expand Down

0 comments on commit 04a60b3

Please sign in to comment.