-
Notifications
You must be signed in to change notification settings - Fork 0
/
intervals.go
124 lines (117 loc) · 2.99 KB
/
intervals.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package intervals
// Intervals keeps a map of start integers to end integers
type Intervals map[int]int
// New will return an empty set of intervals
func New() Intervals {
return make(Intervals)
}
// Insert adds a new interval.
// If the new interval overlaps with any existing intervals,
// the existing intervals will be collapsed/deleted as necessary.
func (ints Intervals) Insert(start, end int) {
if start > end {
start, end = end, start
}
toDelete := []int{}
startOverlap, endOverlap := -1, -1
for intStart, intEnd := range ints {
if intStart <= start && end <= intEnd {
return
} else if start <= intStart && intEnd <= end {
toDelete = append(toDelete, intStart)
} else if intStart < start && start <= intEnd+1 {
startOverlap = intStart
} else if end >= intStart-1 && end < intEnd {
endOverlap = intStart
}
}
for i := range toDelete {
delete(ints, toDelete[i])
}
if startOverlap < 0 && endOverlap < 0 {
ints[start] = end
} else if startOverlap >= 0 && endOverlap >= 0 {
ints[startOverlap] = ints[endOverlap]
delete(ints, endOverlap)
} else if startOverlap >= 0 {
ints[startOverlap] = end
} else if endOverlap >= 0 {
ints[start] = ints[endOverlap]
delete(ints, endOverlap)
}
}
// Delete removes the specified interval.
// If the interval overlaps with existing intervals,
// those intervals are updated/deleted as necessary.
func (ints Intervals) Delete(start, end int) {
if start > end {
start, end = end, start
}
toDelete := []int{}
startOverlap, endOverlap := -1, -1
for intStart, intEnd := range ints {
if start == intStart && end == intEnd {
toDelete = append(toDelete, intStart)
break
} else if intStart < start && end < intEnd {
ints[intStart] = start - 1
ints[end+1] = intEnd
break
} else if start <= intStart && intEnd <= end {
toDelete = append(toDelete, intStart)
} else if intStart < start && start <= intEnd {
startOverlap = intStart
} else if intStart <= end && end < intEnd {
endOverlap = intStart
}
}
for i := range toDelete {
delete(ints, toDelete[i])
}
if startOverlap >= 0 {
ints[startOverlap] = start - 1
}
if endOverlap >= 0 {
ints[end+1] = ints[endOverlap]
delete(ints, endOverlap)
}
}
// Contains will check if there is an interval that contains
// the specified integer.
func (ints Intervals) Contains(x int) bool {
for start, end := range ints {
if start <= x && x <= end {
return true
}
}
return false
}
// Overlaps will check to see if the specified interval overlaps
// with any existing intervals
func (ints Intervals) Overlaps(x, y int) bool {
if x > y {
x, y = y, x
}
for start, end := range ints {
if start <= x && x <= end {
return true
} else if start <= y && y <= end {
return true
} else if x <= start && end <= y {
return true
}
}
return false
}
// Equal returns whether two Intervals are equal
func Equal(x, y Intervals) bool {
if len(x) != len(y) {
return false
}
for i := range x {
if _, ok := y[i]; !ok || y[i] != x[i] {
return false
}
}
return true
}