multi_range 0.0.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.rubocop.yml +8 -9
- data/.travis.yml +1 -5
- data/CHANGELOG.md +14 -1
- data/README.md +132 -5
- data/bin/console +0 -0
- data/bin/setup +1 -1
- data/lib/multi_range.rb +119 -22
- data/lib/multi_range/version.rb +3 -1
- data/multi_range.gemspec +6 -2
- metadata +36 -10
- data/gemfiles/ruby_1_8_7.gemfile +0 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8b6430c0f1e34bd416c5ac86b7427a287b980282604b7220a518feb8eb90e3d3
|
|
4
|
+
data.tar.gz: 01f8ca6da27bc8a960ef531e114cdfc15296fac6af91e4e588642a11b7b56ac7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a14a3bee4fece94aa0c39a8fcdd614dfcd94afe771a7075f84e33093cf3a0e5e8990029685f09bc89b13c93d1ce89b82bc527c0f120f43f0238e39e902fd6a28
|
|
7
|
+
data.tar.gz: 513bba26a2dee77e82720214102e9231390954e94cdf36cff610066578179ea67498bfd29576ceb9177362981f34baad2abdddca877f782dc0b47123523e71b0
|
data/.rubocop.yml
CHANGED
|
@@ -76,10 +76,6 @@ Layout/EndAlignment:
|
|
|
76
76
|
Description: 'Align ends correctly.'
|
|
77
77
|
Enabled: true
|
|
78
78
|
|
|
79
|
-
Lint/EndInMethod:
|
|
80
|
-
Description: 'END blocks should not be placed inside method definitions.'
|
|
81
|
-
Enabled: true
|
|
82
|
-
|
|
83
79
|
Lint/EnsureReturn:
|
|
84
80
|
Description: 'Do not use return in an ensure block.'
|
|
85
81
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-return-ensure'
|
|
@@ -181,8 +177,8 @@ Lint/UselessAssignment:
|
|
|
181
177
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars'
|
|
182
178
|
Enabled: true
|
|
183
179
|
|
|
184
|
-
Lint/
|
|
185
|
-
Description: '
|
|
180
|
+
Lint/BinaryOperatorWithIdenticalOperands:
|
|
181
|
+
Description: 'This cop checks for places where binary operator has identical operands.'
|
|
186
182
|
Enabled: true
|
|
187
183
|
|
|
188
184
|
Lint/UselessElseWithoutRescue:
|
|
@@ -581,9 +577,12 @@ Style/For:
|
|
|
581
577
|
Style/FormatString:
|
|
582
578
|
Description: 'Enforce the use of Kernel#sprintf, Kernel#format or String#%.'
|
|
583
579
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#sprintf'
|
|
584
|
-
EnforcedStyle:
|
|
580
|
+
EnforcedStyle: percent
|
|
585
581
|
Enabled: true
|
|
586
582
|
|
|
583
|
+
Style/FormatStringToken:
|
|
584
|
+
Enabled: false
|
|
585
|
+
|
|
587
586
|
Style/GlobalVars:
|
|
588
587
|
Description: 'Do not introduce global variables.'
|
|
589
588
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#instance-vars'
|
|
@@ -809,7 +808,7 @@ Style/PercentQLiterals:
|
|
|
809
808
|
Style/PerlBackrefs:
|
|
810
809
|
Description: 'Avoid Perl-style regex back references.'
|
|
811
810
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers'
|
|
812
|
-
Enabled:
|
|
811
|
+
Enabled: false
|
|
813
812
|
|
|
814
813
|
Naming/PredicateName:
|
|
815
814
|
Description: 'Check the names of predicate methods.'
|
|
@@ -1065,7 +1064,7 @@ Style/SymbolProc:
|
|
|
1065
1064
|
Description: 'Use symbols as procs instead of blocks when possible.'
|
|
1066
1065
|
Enabled: false # wants to support ruby 1.8
|
|
1067
1066
|
|
|
1068
|
-
Layout/
|
|
1067
|
+
Layout/IndentationStyle:
|
|
1069
1068
|
Description: 'No hard tabs.'
|
|
1070
1069
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-indentation'
|
|
1071
1070
|
Enabled: true
|
data/.travis.yml
CHANGED
|
@@ -4,16 +4,12 @@ env:
|
|
|
4
4
|
- CC_TEST_REPORTER_ID=a2bb1313ac63f7ae7a7f13ac962870e3cdb0c345b6c60d2857807cc5153d7c3b
|
|
5
5
|
language: ruby
|
|
6
6
|
rvm:
|
|
7
|
+
- 2.0
|
|
7
8
|
- 2.2
|
|
8
9
|
- 2.6
|
|
9
10
|
- 2.7
|
|
10
11
|
gemfile:
|
|
11
12
|
- gemfiles/Gemfile
|
|
12
|
-
matrix:
|
|
13
|
-
include:
|
|
14
|
-
- dist: trusty
|
|
15
|
-
rvm: 1.8.7
|
|
16
|
-
gemfile: gemfiles/ruby_1_8_7.gemfile
|
|
17
13
|
before_install:
|
|
18
14
|
- if `ruby -e 'exit(RUBY_VERSION.to_f < 2.7)'`; then
|
|
19
15
|
gem i rubygems-update -v '< 3' && update_rubygems;
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
## Change Log
|
|
2
2
|
|
|
3
|
+
### [v1.1.0](https://github.com/khiav223577/multi_range/compare/v1.0.0...v1.1.0) 2020/10/15
|
|
4
|
+
- [#13](https://github.com/khiav223577/multi_range/pull/13) Rename flatten => merge_overlaps (@khiav223577)
|
|
5
|
+
|
|
6
|
+
### [v1.0.0](https://github.com/khiav223577/multi_range/compare/v0.0.4...v1.0.0) 2020/10/15
|
|
7
|
+
- [#12](https://github.com/khiav223577/multi_range/pull/12) Implement #overlaps? (@khiav223577)
|
|
8
|
+
- [#11](https://github.com/khiav223577/multi_range/pull/11) Support difference other multi_range object (@khiav223577)
|
|
9
|
+
- [#10](https://github.com/khiav223577/multi_range/pull/10) Add frozen_string_literal (@khiav223577)
|
|
10
|
+
- [#9](https://github.com/khiav223577/multi_range/pull/9) Implement range union (@khiav223577)
|
|
11
|
+
- [#8](https://github.com/khiav223577/multi_range/pull/8) Support initializing a MultiRange object with unsorted ranges (@khiav223577)
|
|
12
|
+
|
|
13
|
+
### [v0.0.4](https://github.com/khiav223577/multi_range/compare/v0.0.3...v0.0.4) 2020/03/26
|
|
14
|
+
- [#7](https://github.com/khiav223577/multi_range/pull/7) Add flatten method (@khiav223577)
|
|
15
|
+
|
|
3
16
|
### [v0.0.3](https://github.com/khiav223577/multi_range/compare/v0.0.2...v0.0.3) 2020/03/02
|
|
4
17
|
- [#6](https://github.com/khiav223577/multi_range/pull/6) freeze internal ranges variable (@khiav223577)
|
|
5
18
|
- [#5](https://github.com/khiav223577/multi_range/pull/5) Add min, max, to_a method (@khiav223577)
|
|
@@ -8,6 +21,6 @@
|
|
|
8
21
|
- [#4](https://github.com/khiav223577/multi_range/pull/4) Add each, map, index_with methods (@khiav223577)
|
|
9
22
|
- [#3](https://github.com/khiav223577/multi_range/pull/3) Support passing integer as range (@khiav223577)
|
|
10
23
|
|
|
11
|
-
### v0.0.1 2020/03/01
|
|
24
|
+
### [v0.0.1](https://github.com/khiav223577/multi_range/compare/v0.0.1...v0.0.1) 2020/03/01
|
|
12
25
|
- [#2](https://github.com/khiav223577/multi_range/pull/2) Support Ruby 1.8.7 (@khiav223577)
|
|
13
26
|
- [#1](https://github.com/khiav223577/multi_range/pull/1) Implement MultiRange (@khiav223577)
|
data/README.md
CHANGED
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
[](https://codeclimate.com/github/khiav223577/multi_range/coverage)
|
|
8
8
|
|
|
9
9
|
## Supports
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
- Ruby 2.0 ~ 2.7
|
|
12
|
+
|
|
13
|
+
For Ruby 1.8.x and 1.9.x, please use multi_range < 2.
|
|
11
14
|
|
|
12
15
|
## Installation
|
|
13
16
|
|
|
@@ -25,7 +28,7 @@ Or install it yourself as:
|
|
|
25
28
|
|
|
26
29
|
## Usage
|
|
27
30
|
|
|
28
|
-
Allow you to manipulate a group of ranges.
|
|
31
|
+
Allow you to manipulate a group of ranges. Such as merging overlapping ranges, doing ranges union, intersection, and difference.
|
|
29
32
|
|
|
30
33
|
### Sample a number
|
|
31
34
|
```rb
|
|
@@ -34,7 +37,7 @@ multi_range.sample
|
|
|
34
37
|
# => equals to [1, 2, 3, 4, 5, 10, 11, 12].sample
|
|
35
38
|
```
|
|
36
39
|
|
|
37
|
-
###
|
|
40
|
+
### Difference of ranges
|
|
38
41
|
```rb
|
|
39
42
|
multi_range = MultiRange.new([1..10])
|
|
40
43
|
multi_range -= 5..7
|
|
@@ -49,11 +52,91 @@ multi_range.ranges
|
|
|
49
52
|
# => [1...5, 86..100]
|
|
50
53
|
```
|
|
51
54
|
|
|
52
|
-
|
|
55
|
+
```rb
|
|
56
|
+
multi_range = MultiRange.new([1..10, 50..70, 80..100])
|
|
57
|
+
multi_range -= MultiRange.new([5..60, 75..85])
|
|
58
|
+
multi_range.ranges
|
|
59
|
+
# => [1...5, 61..70, 86..100]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Union ranges
|
|
63
|
+
|
|
64
|
+
```rb
|
|
65
|
+
multi_range = MultiRange.new([1..5])
|
|
66
|
+
multi_range |= 3..8
|
|
67
|
+
multi_range.ranges
|
|
68
|
+
# => [1..8]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```rb
|
|
72
|
+
multi_range = MultiRange.new([1..5, 10..15, 20..25])
|
|
73
|
+
multi_range |= MultiRange.new([3..6, 14..22, 30])
|
|
74
|
+
multi_range.ranges
|
|
75
|
+
# => [1..6, 10..25, 30..30]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Intersection ranges
|
|
79
|
+
|
|
80
|
+
```rb
|
|
81
|
+
multi_range = MultiRange.new([1..5])
|
|
82
|
+
multi_range &= 3..8
|
|
83
|
+
multi_range.ranges
|
|
84
|
+
# => [3..5]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```rb
|
|
88
|
+
multi_range = MultiRange.new([1..3, 5..10])
|
|
89
|
+
multi_range &= MultiRange.new([2..6, 8..9])
|
|
90
|
+
multi_range.ranges
|
|
91
|
+
# => [2..3, 5..6, 8..9]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Merge overlaps
|
|
53
95
|
```rb
|
|
54
96
|
multi_range = MultiRange.new([1, 2, 4..6, 7, 8..12])
|
|
55
|
-
multi_range.
|
|
97
|
+
multi_range.merge_overlaps.ranges
|
|
56
98
|
# => [1..2, 4..12]
|
|
99
|
+
|
|
100
|
+
multi_range = MultiRange.new([1.2..1.5, 1.7..1.9, 1.8..2.2])
|
|
101
|
+
multi_range.merge_overlaps.ranges
|
|
102
|
+
# => [1.2..1.5, 1.7..2.2]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Check if it overlaps with the other
|
|
106
|
+
|
|
107
|
+
```rb
|
|
108
|
+
multi_range = MultiRange.new([1..5, 10..15, 20..25])
|
|
109
|
+
multi_range.overlaps?(7..8)
|
|
110
|
+
# => false
|
|
111
|
+
|
|
112
|
+
multi_range.overlaps?(3..8)
|
|
113
|
+
# => true
|
|
114
|
+
|
|
115
|
+
multi_range.overlaps?(7..12)
|
|
116
|
+
# => true
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
```rb
|
|
120
|
+
multi_range = MultiRange.new([1..5, 10..15, 20..25])
|
|
121
|
+
multi_range.overlaps?(MultiRange.new([6..8, 18..22]))
|
|
122
|
+
# => true
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
### Check if it contains overlaps
|
|
127
|
+
|
|
128
|
+
```rb
|
|
129
|
+
MultiRange.new([0..3, 5..10, 20..50]).contain_overlaps?
|
|
130
|
+
# => false
|
|
131
|
+
|
|
132
|
+
MultiRange.new([0...5, 5..10, 20..50]).contain_overlaps?
|
|
133
|
+
# => false
|
|
134
|
+
|
|
135
|
+
MultiRange.new([0..5, 5..10, 20..50]).contain_overlaps?
|
|
136
|
+
# => true
|
|
137
|
+
|
|
138
|
+
MultiRange.new([0...7, 5..10, 20..50]).contain_overlaps?
|
|
139
|
+
# => true
|
|
57
140
|
```
|
|
58
141
|
|
|
59
142
|
### Range-like interface
|
|
@@ -94,6 +177,50 @@ MultiRange.new([1..3, 6, 8..9]).to_a
|
|
|
94
177
|
# => [1, 2, 3, 6, 8, 9]
|
|
95
178
|
```
|
|
96
179
|
|
|
180
|
+
|
|
181
|
+
#### size
|
|
182
|
+
```rb
|
|
183
|
+
MultiRange.new([1..3, 6, 8..9]).size
|
|
184
|
+
# => 6
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Warning
|
|
188
|
+
|
|
189
|
+
The return value may be different when there are some overlapped ranges.
|
|
190
|
+
Call `merge_overlaps` if you want to merge overlapped ranges.
|
|
191
|
+
|
|
192
|
+
```rb
|
|
193
|
+
MultiRange.new([1..5, 3..6]).to_a
|
|
194
|
+
# => [1, 2, 3, 4, 5, 3, 4, 5, 6]
|
|
195
|
+
|
|
196
|
+
MultiRange.new([1..5, 3..6]).merge_overlaps.to_a
|
|
197
|
+
# => [1, 2, 3, 4, 5, 6]
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
```rb
|
|
201
|
+
MultiRange.new([1..5, 3..6]).each{|s| print s }
|
|
202
|
+
# => 123453456
|
|
203
|
+
|
|
204
|
+
MultiRange.new([1..5, 3..6]).merge_overlaps.each{|s| print s }
|
|
205
|
+
# => 123456
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
```rb
|
|
209
|
+
MultiRange.new([1..5, 3..6]).map{|s| s * 2 }
|
|
210
|
+
# => [2, 4, 6, 8, 10, 6, 8, 10, 12]
|
|
211
|
+
|
|
212
|
+
MultiRange.new([1..5, 3..6]).merge_overlaps.map{|s| s * 2 }
|
|
213
|
+
# => [2, 4, 6, 8, 10, 12]
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
```rb
|
|
217
|
+
MultiRange.new([1..5, 3..6]).size
|
|
218
|
+
# => 9
|
|
219
|
+
|
|
220
|
+
MultiRange.new([1..5, 3..6]).merge_overlaps.size
|
|
221
|
+
# => 6
|
|
222
|
+
```
|
|
223
|
+
|
|
97
224
|
## Development
|
|
98
225
|
|
|
99
226
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/bin/console
CHANGED
|
File without changes
|
data/bin/setup
CHANGED
data/lib/multi_range.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'multi_range/version'
|
|
2
4
|
require 'roulette-wheel-selection'
|
|
5
|
+
require 'interval_tree'
|
|
3
6
|
|
|
4
7
|
if not Range.method_defined?(:size)
|
|
5
8
|
warn "Please backports Range#size method to use multi_range gem.\n" \
|
|
@@ -19,25 +22,35 @@ class MultiRange
|
|
|
19
22
|
|
|
20
23
|
attr_reader :ranges
|
|
21
24
|
|
|
22
|
-
def initialize(ranges)
|
|
23
|
-
|
|
25
|
+
def initialize(ranges)
|
|
26
|
+
if ranges.is_a? MultiRange
|
|
27
|
+
@ranges = ranges.ranges
|
|
28
|
+
@is_float = ranges.is_float?
|
|
29
|
+
else
|
|
30
|
+
@ranges = ranges.map{|s| s.is_a?(Numeric) ? s..s : s }.sort_by(&:begin).freeze
|
|
31
|
+
@is_float = @ranges.any?{|range| range.begin.is_a?(Float) || range.end.is_a?(Float) }
|
|
32
|
+
end
|
|
24
33
|
end
|
|
25
34
|
|
|
26
|
-
def
|
|
27
|
-
|
|
35
|
+
def is_float?
|
|
36
|
+
@is_float
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def merge_overlaps(merge_same_value = true)
|
|
40
|
+
return MultiRange.new([]) if @ranges.size == 0
|
|
28
41
|
|
|
29
42
|
new_ranges = []
|
|
30
43
|
current_range = nil
|
|
31
44
|
|
|
32
45
|
@ranges.each do |range|
|
|
33
46
|
next current_range = range if current_range == nil
|
|
34
|
-
next if range.
|
|
47
|
+
next if range.end <= current_range.end
|
|
35
48
|
|
|
36
|
-
if current_range
|
|
49
|
+
if can_combine?(current_range, range, merge_same_value)
|
|
50
|
+
current_range = range.exclude_end? ? current_range.begin...range.end : current_range.begin..range.end
|
|
51
|
+
else
|
|
37
52
|
new_ranges << current_range
|
|
38
53
|
current_range = range
|
|
39
|
-
else
|
|
40
|
-
current_range = current_range.min..range.max
|
|
41
54
|
end
|
|
42
55
|
end
|
|
43
56
|
|
|
@@ -45,33 +58,63 @@ class MultiRange
|
|
|
45
58
|
return MultiRange.new(new_ranges)
|
|
46
59
|
end
|
|
47
60
|
|
|
61
|
+
def &(other)
|
|
62
|
+
other_ranges = MultiRange.new(other).merge_overlaps.ranges
|
|
63
|
+
tree = IntervalTree::Tree.new(other_ranges)
|
|
64
|
+
intersected_ranges = merge_overlaps.ranges.flat_map do |range|
|
|
65
|
+
matching_ranges_converted_to_exclusive = tree.search(range) || []
|
|
66
|
+
|
|
67
|
+
# The interval tree converts interval endings to exclusive, so we need to restore the original
|
|
68
|
+
matching_ranges = matching_ranges_converted_to_exclusive.map do |matching_range_converted_to_exclusive|
|
|
69
|
+
other_ranges.find do |other_range|
|
|
70
|
+
# Having merged overlaps in each multirange, there's no need to check the endings, since there will only be one range with each beginning
|
|
71
|
+
other_range.begin == matching_range_converted_to_exclusive.begin
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
matching_ranges.map do |matching_range|
|
|
76
|
+
intersect_two_ranges(range, matching_range)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
MultiRange.new(intersected_ranges)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
alias intersection &
|
|
83
|
+
|
|
48
84
|
def -(other)
|
|
49
|
-
|
|
85
|
+
return difference_with_other_multi_range(other) if other.is_a?(MultiRange)
|
|
50
86
|
|
|
51
|
-
|
|
52
|
-
return MultiRange.new(new_ranges) if other
|
|
53
|
-
return MultiRange.new(new_ranges) if other.max < @ranges.first.min # 小於最小值
|
|
87
|
+
new_ranges = @ranges.dup
|
|
88
|
+
return MultiRange.new(new_ranges) if not overlaps_with_range?(other)
|
|
54
89
|
|
|
55
90
|
changed_size = 0
|
|
56
91
|
@ranges.each_with_index do |range, idx|
|
|
57
|
-
next if other.
|
|
58
|
-
break if other.
|
|
59
|
-
|
|
60
|
-
sub_range1 = range.min...other.min
|
|
61
|
-
sub_range2 = (other.max + 1)..range.max
|
|
62
|
-
|
|
63
|
-
sub_ranges = []
|
|
64
|
-
sub_ranges << sub_range1 if sub_range1.any?
|
|
65
|
-
sub_ranges << sub_range2 if sub_range2.any?
|
|
92
|
+
next if other.begin > range.end # 大於這個 range
|
|
93
|
+
break if other.end < range.begin # 小於這個 range
|
|
66
94
|
|
|
95
|
+
sub_ranges = possible_sub_ranges_of(range, other)
|
|
67
96
|
new_ranges[idx + changed_size, 1] = sub_ranges
|
|
68
97
|
changed_size += sub_ranges.size - 1
|
|
69
|
-
break if other.
|
|
98
|
+
break if other.end <= range.end # 沒有超過一個 range 的範圍
|
|
70
99
|
end
|
|
71
100
|
|
|
72
101
|
return MultiRange.new(new_ranges)
|
|
73
102
|
end
|
|
74
103
|
|
|
104
|
+
alias difference -
|
|
105
|
+
|
|
106
|
+
def |(other)
|
|
107
|
+
other_ranges = other.is_a?(MultiRange) ? other.ranges : [other]
|
|
108
|
+
return MultiRange.new(@ranges + other_ranges).merge_overlaps
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
alias union |
|
|
112
|
+
|
|
113
|
+
def overlaps?(other)
|
|
114
|
+
multi_range = merge_overlaps
|
|
115
|
+
return multi_range.ranges != (multi_range - other).ranges
|
|
116
|
+
end
|
|
117
|
+
|
|
75
118
|
def sample
|
|
76
119
|
range = RouletteWheelSelection.sample(@ranges.map{|s| [s, s.size] }.to_h)
|
|
77
120
|
return nil if range == nil
|
|
@@ -122,4 +165,58 @@ class MultiRange
|
|
|
122
165
|
range = @ranges.last
|
|
123
166
|
return range.max if range
|
|
124
167
|
end
|
|
168
|
+
|
|
169
|
+
def contain_overlaps?
|
|
170
|
+
merge_overlaps(false).ranges != ranges
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
private
|
|
174
|
+
|
|
175
|
+
# make sure that range1.begin <= range2.begin
|
|
176
|
+
def can_combine?(range1, range2, merge_same_value)
|
|
177
|
+
return merge_same_value if range1.end == range2.begin and range1.exclude_end?
|
|
178
|
+
return range1.end >= range2.begin if @is_float
|
|
179
|
+
return range1.end + 1 >= range2.begin
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def difference_with_other_multi_range(other)
|
|
183
|
+
new_multi_range = dup
|
|
184
|
+
other.ranges.each{|range| new_multi_range -= range }
|
|
185
|
+
return new_multi_range
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def possible_sub_ranges_of(range, other)
|
|
189
|
+
sub_range1 = range.begin...other.begin
|
|
190
|
+
|
|
191
|
+
sub_range2_begin = if other.exclude_end?
|
|
192
|
+
other.end
|
|
193
|
+
else
|
|
194
|
+
other.end + (other.end.is_a?(Float) ? Float::EPSILON : 1)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
sub_range2 = range.exclude_end? ? sub_range2_begin...range.end : sub_range2_begin..range.end
|
|
198
|
+
|
|
199
|
+
sub_ranges = []
|
|
200
|
+
sub_ranges << sub_range1 if sub_range1.begin <= sub_range1.end
|
|
201
|
+
sub_ranges << sub_range2 if sub_range2.begin <= sub_range2.end
|
|
202
|
+
return sub_ranges
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def overlaps_with_range?(range)
|
|
206
|
+
return false if @ranges.empty?
|
|
207
|
+
return false if range.begin > @ranges.last.end # larger than maxinum
|
|
208
|
+
return false if range.end < @ranges.first.begin # smaller than mininum
|
|
209
|
+
return true
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def intersect_two_ranges(range_a, range_b)
|
|
213
|
+
ranges = [range_a, range_b]
|
|
214
|
+
start = ranges.map(&:begin).max
|
|
215
|
+
finish = ranges.map(&:end).min
|
|
216
|
+
if ranges.sort_by { |range| [range.end, range.exclude_end? ? 1 : 0] }.first.exclude_end?
|
|
217
|
+
start...finish
|
|
218
|
+
else
|
|
219
|
+
start..finish
|
|
220
|
+
end
|
|
221
|
+
end
|
|
125
222
|
end
|
data/lib/multi_range/version.rb
CHANGED
data/multi_range.gemspec
CHANGED
|
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.authors = ['khiav reoy']
|
|
10
10
|
spec.email = ['mrtmrt15xn@yahoo.com.tw']
|
|
11
11
|
|
|
12
|
-
spec.summary = '
|
|
13
|
-
spec.description = '
|
|
12
|
+
spec.summary = 'Allow you to manipulate a group of ranges. Such as merging overlapping ranges, doing ranges union and difference.'
|
|
13
|
+
spec.description = 'Allow you to manipulate a group of ranges. Such as merging overlapping ranges, doing ranges union and difference.'
|
|
14
14
|
spec.homepage = 'https://github.com/khiav223577/multi_range'
|
|
15
15
|
spec.license = 'MIT'
|
|
16
16
|
|
|
@@ -34,10 +34,14 @@ Gem::Specification.new do |spec|
|
|
|
34
34
|
'bug_tracker_uri' => 'https://github.com/khiav223577/multi_range/issues',
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
spec.required_ruby_version = '>= 2.0'
|
|
38
|
+
|
|
37
39
|
spec.add_development_dependency 'bundler', '>= 1.17', '< 3.x'
|
|
38
40
|
spec.add_development_dependency 'rake', '>= 10.5.0'
|
|
39
41
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
|
42
|
+
spec.add_development_dependency 'minitest-color', '~> 0.0.2'
|
|
40
43
|
spec.add_development_dependency 'backports', '~> 3.15.0'
|
|
41
44
|
|
|
42
45
|
spec.add_dependency 'roulette-wheel-selection', '~> 1.1.1'
|
|
46
|
+
spec.add_dependency 'fast_interval_tree', '~> 0.2.0'
|
|
43
47
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: multi_range
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- khiav reoy
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-11-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -58,6 +58,20 @@ dependencies:
|
|
|
58
58
|
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
60
|
version: '5.0'
|
|
61
|
+
- !ruby/object:Gem::Dependency
|
|
62
|
+
name: minitest-color
|
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: 0.0.2
|
|
68
|
+
type: :development
|
|
69
|
+
prerelease: false
|
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: 0.0.2
|
|
61
75
|
- !ruby/object:Gem::Dependency
|
|
62
76
|
name: backports
|
|
63
77
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -86,8 +100,22 @@ dependencies:
|
|
|
86
100
|
- - "~>"
|
|
87
101
|
- !ruby/object:Gem::Version
|
|
88
102
|
version: 1.1.1
|
|
89
|
-
|
|
90
|
-
|
|
103
|
+
- !ruby/object:Gem::Dependency
|
|
104
|
+
name: fast_interval_tree
|
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 0.2.0
|
|
110
|
+
type: :runtime
|
|
111
|
+
prerelease: false
|
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: 0.2.0
|
|
117
|
+
description: Allow you to manipulate a group of ranges. Such as merging overlapping
|
|
118
|
+
ranges, doing ranges union and difference.
|
|
91
119
|
email:
|
|
92
120
|
- mrtmrt15xn@yahoo.com.tw
|
|
93
121
|
executables: []
|
|
@@ -105,7 +133,6 @@ files:
|
|
|
105
133
|
- bin/console
|
|
106
134
|
- bin/setup
|
|
107
135
|
- gemfiles/Gemfile
|
|
108
|
-
- gemfiles/ruby_1_8_7.gemfile
|
|
109
136
|
- lib/multi_range.rb
|
|
110
137
|
- lib/multi_range/version.rb
|
|
111
138
|
- multi_range.gemspec
|
|
@@ -126,17 +153,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
126
153
|
requirements:
|
|
127
154
|
- - ">="
|
|
128
155
|
- !ruby/object:Gem::Version
|
|
129
|
-
version: '0'
|
|
156
|
+
version: '2.0'
|
|
130
157
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
158
|
requirements:
|
|
132
159
|
- - ">="
|
|
133
160
|
- !ruby/object:Gem::Version
|
|
134
161
|
version: '0'
|
|
135
162
|
requirements: []
|
|
136
|
-
|
|
137
|
-
rubygems_version: 2.6.14
|
|
163
|
+
rubygems_version: 3.0.3
|
|
138
164
|
signing_key:
|
|
139
165
|
specification_version: 4
|
|
140
|
-
summary:
|
|
141
|
-
|
|
166
|
+
summary: Allow you to manipulate a group of ranges. Such as merging overlapping ranges,
|
|
167
|
+
doing ranges union and difference.
|
|
142
168
|
test_files: []
|