range_list 0.1.0 → 1.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 +4 -4
- data/Gemfile +8 -0
- data/Gemfile.lock +67 -0
- data/README.md +41 -12
- data/lib/range_list/errors.rb +7 -0
- data/lib/range_list/version.rb +2 -2
- data/lib/range_list.rb +137 -3
- data/range_list.gemspec +2 -0
- metadata +20 -4
- data/sig/range_list.rbs +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f27b8cd8551942e4ff09f2cc32c525e7fd5724cdbea8e322203cd01df681fb46
|
4
|
+
data.tar.gz: c24ffbe52e439561c2010fccdf67f68d9700703b23c4ed45d34c143ba5e6de46
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62a1a66f4607c3e17424d8bd76cd8371626e8ff0d64961f189f09534fb33cc6e60537e821b3bb743389057db0c76a4e5e83cd7cbe8d3a6872c6c808891237f16
|
7
|
+
data.tar.gz: 9fb515423d8048f124e15a88cb3c5b718e7d273694bb8e9fe128ce2e37ebda636ba1da330af406abfc57d8566686fa71eff91d88c7af1eee55cd9b5b4ad75ad1
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
range_list (1.0.0)
|
5
|
+
treemap (~> 1.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
ast (2.4.2)
|
11
|
+
docile (1.4.0)
|
12
|
+
minitest (5.15.0)
|
13
|
+
parallel (1.21.0)
|
14
|
+
parser (3.1.1.0)
|
15
|
+
ast (~> 2.4.1)
|
16
|
+
rainbow (3.1.1)
|
17
|
+
rake (13.0.6)
|
18
|
+
regexp_parser (2.2.1)
|
19
|
+
rexml (3.2.5)
|
20
|
+
rubocop (1.25.1)
|
21
|
+
parallel (~> 1.10)
|
22
|
+
parser (>= 3.1.0.0)
|
23
|
+
rainbow (>= 2.2.2, < 4.0)
|
24
|
+
regexp_parser (>= 1.8, < 3.0)
|
25
|
+
rexml
|
26
|
+
rubocop-ast (>= 1.15.1, < 2.0)
|
27
|
+
ruby-progressbar (~> 1.7)
|
28
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
29
|
+
rubocop-ast (1.16.0)
|
30
|
+
parser (>= 3.1.1.0)
|
31
|
+
rubocop-performance (1.13.2)
|
32
|
+
rubocop (>= 1.7.0, < 2.0)
|
33
|
+
rubocop-ast (>= 0.4.0)
|
34
|
+
ruby-progressbar (1.11.0)
|
35
|
+
simplecov (0.21.2)
|
36
|
+
docile (~> 1.1)
|
37
|
+
simplecov-html (~> 0.11)
|
38
|
+
simplecov_json_formatter (~> 0.1)
|
39
|
+
simplecov-cobertura (2.1.0)
|
40
|
+
rexml
|
41
|
+
simplecov (~> 0.19)
|
42
|
+
simplecov-html (0.12.3)
|
43
|
+
simplecov_json_formatter (0.1.4)
|
44
|
+
standard (1.7.2)
|
45
|
+
rubocop (= 1.25.1)
|
46
|
+
rubocop-performance (= 1.13.2)
|
47
|
+
treemap (1.0.3)
|
48
|
+
unicode-display_width (2.1.0)
|
49
|
+
webrick (1.7.0)
|
50
|
+
yard (0.9.27)
|
51
|
+
webrick (~> 1.7.0)
|
52
|
+
|
53
|
+
PLATFORMS
|
54
|
+
ruby
|
55
|
+
x86_64-darwin-19
|
56
|
+
|
57
|
+
DEPENDENCIES
|
58
|
+
minitest (~> 5.0)
|
59
|
+
rake (~> 13.0)
|
60
|
+
range_list!
|
61
|
+
simplecov (~> 0.21.2)
|
62
|
+
simplecov-cobertura (~> 2.1)
|
63
|
+
standard (~> 1.7)
|
64
|
+
yard (~> 0.9.27)
|
65
|
+
|
66
|
+
BUNDLED WITH
|
67
|
+
2.3.8
|
data/README.md
CHANGED
@@ -1,28 +1,57 @@
|
|
1
1
|
# RangeList
|
2
2
|
|
3
|
-
|
3
|
+
A pair of integers define a range, for example: [1, 5), this range includes integers: 1, 2, 3, and 4.
|
4
|
+
A range list is an aggregate of these ranges: [1, 5), [10, 11), [100, 201).
|
4
5
|
|
5
|
-
|
6
|
+
RangeList offers `add`, `remove`, `print`, `containsAll?`, `containsAny?` methods, and offers the `Enumerable` ability,
|
7
|
+
you can handle ranges more easily.
|
8
|
+
|
9
|
+
[](https://rubygems.org/gems/range_list)
|
10
|
+
[](https://rubydoc.info/gems/range_list)
|
11
|
+
[](https://gitlab.com/songhuangcn/range_list/-/commits/main)
|
12
|
+
[](https://gitlab.com/songhuangcn/range_list/-/commits/main)
|
6
13
|
|
7
14
|
## Installation
|
8
15
|
|
9
|
-
Add
|
16
|
+
Add gem to your application's Gemfile:
|
10
17
|
|
11
|
-
```
|
12
|
-
|
18
|
+
```shell
|
19
|
+
bundle add range_list
|
13
20
|
```
|
14
21
|
|
15
|
-
And then execute:
|
16
|
-
|
17
|
-
$ bundle install
|
18
|
-
|
19
22
|
Or install it yourself as:
|
20
23
|
|
21
|
-
|
24
|
+
```shell
|
25
|
+
gem install range_list
|
26
|
+
```
|
22
27
|
|
23
28
|
## Usage
|
24
29
|
|
25
|
-
|
30
|
+
```shell
|
31
|
+
range_list = RangeList.new
|
32
|
+
range_list.add([1, 5]).add([10, 20])
|
33
|
+
range_list.print # [1, 5) [10, 20)
|
34
|
+
|
35
|
+
range_list.add([20, 20])
|
36
|
+
range_list.print # [1, 5) [10, 20)
|
37
|
+
|
38
|
+
range_list.add([15, 21])
|
39
|
+
range_list.print # [1, 5) [10, 21)
|
40
|
+
|
41
|
+
range_list.remove([15, 21])
|
42
|
+
range_list.print # [1, 5) [10, 15)
|
43
|
+
|
44
|
+
range_list.contains_any?([8, 10]) # false
|
45
|
+
range_list.contains_any?([8, 11]) # true
|
46
|
+
range_list.contains_all?([8, 11]) # false
|
47
|
+
range_list.contains_all?([10, 11]) # true
|
48
|
+
|
49
|
+
range_list.each { |range_start, range_end| puts "#{range_start} <= x < #{range_end}" } # print all range in order
|
50
|
+
|
51
|
+
range_list.remove([0, 100])
|
52
|
+
range_list.print #
|
53
|
+
range_list.to_a # []
|
54
|
+
```
|
26
55
|
|
27
56
|
## Development
|
28
57
|
|
@@ -32,7 +61,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
61
|
|
33
62
|
## Contributing
|
34
63
|
|
35
|
-
Bug reports and
|
64
|
+
Bug reports and Merge requests are welcome on GitLab at https://gitlab.com/songhuangcn/range_list.
|
36
65
|
|
37
66
|
## License
|
38
67
|
|
data/lib/range_list/version.rb
CHANGED
data/lib/range_list.rb
CHANGED
@@ -1,8 +1,142 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "treemap"
|
3
4
|
require_relative "range_list/version"
|
5
|
+
require_relative "range_list/errors"
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
class RangeList
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@tree = TreeMap.new
|
12
|
+
end
|
13
|
+
|
14
|
+
# Add range into current range list.
|
15
|
+
# @param range [Array<Integer>] the range, first element is range start, second is range end.
|
16
|
+
# Range end need be greater or equal than range start.
|
17
|
+
# @return [RangeList]
|
18
|
+
def add(range)
|
19
|
+
validate_range!(range)
|
20
|
+
|
21
|
+
# Return when range is empty.
|
22
|
+
return self if empty_range?(range)
|
23
|
+
|
24
|
+
# Get real range start.
|
25
|
+
start_floor_entry = tree.floor_entry(range[0])
|
26
|
+
range_start = if !start_floor_entry.nil? && start_floor_entry.value >= range[0]
|
27
|
+
start_floor_entry.key
|
28
|
+
else
|
29
|
+
range[0]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get real range end.
|
33
|
+
end_floor_entry = tree.floor_entry(range[1])
|
34
|
+
range_end = if !end_floor_entry.nil? && end_floor_entry.value >= range[1]
|
35
|
+
end_floor_entry.value
|
36
|
+
else
|
37
|
+
range[1]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Insert or replace new range.
|
41
|
+
tree.put(range_start, range_end)
|
42
|
+
|
43
|
+
# Remove keys between range, exclude start, include end.
|
44
|
+
between_maps = tree.sub_map(range[0], false, range[1], true)
|
45
|
+
between_maps.keys.each { |key| tree.remove(key) }
|
46
|
+
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
# Remove range from current range list.
|
51
|
+
# @param (see #add)
|
52
|
+
# @return [RangeList]
|
53
|
+
def remove(range)
|
54
|
+
validate_range!(range)
|
55
|
+
|
56
|
+
# Return when range is empty.
|
57
|
+
return self if empty_range?(range)
|
58
|
+
|
59
|
+
# Insert end lower entry
|
60
|
+
end_lower_entry = tree.lower_entry(range[1])
|
61
|
+
if !end_lower_entry.nil? && end_lower_entry.value > range[1]
|
62
|
+
tree.put(range[1], end_lower_entry.value)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Relace start lower entry
|
66
|
+
start_lower_entry = tree.lower_entry(range[0])
|
67
|
+
if !start_lower_entry.nil? && start_lower_entry.value > range[0]
|
68
|
+
tree.put(start_lower_entry.key, range[0])
|
69
|
+
end
|
70
|
+
|
71
|
+
# Remove keys between range, include start, exclude end
|
72
|
+
between_maps = tree.sub_map(range[0], true, range[1], false)
|
73
|
+
between_maps.keys.each { |key| tree.remove(key) }
|
74
|
+
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
# Print current range list.
|
79
|
+
# @return [void]
|
80
|
+
def print
|
81
|
+
puts to_a.map { |k, v| "[#{k}, #{v})" }.join(" ")
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns true if this set contains all elements of the range.
|
85
|
+
# @param (see #add)
|
86
|
+
# @return [Boolean]
|
87
|
+
# @note return false if the argument range is empty
|
88
|
+
def contains_all?(range)
|
89
|
+
return false if empty_range?(range)
|
90
|
+
|
91
|
+
start_floor_entry = tree.floor_entry(range[0])
|
92
|
+
!start_floor_entry.nil? && start_floor_entry.value >= range[1]
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns true if this set contains any element of the range.
|
96
|
+
# @param (see #add)
|
97
|
+
# @return [Boolean]
|
98
|
+
# @note return false if the argument range is empty
|
99
|
+
def contains_any?(range)
|
100
|
+
return false if empty_range?(range)
|
101
|
+
|
102
|
+
lower_floor_entry = tree.lower_entry(range[1])
|
103
|
+
!lower_floor_entry.nil? && lower_floor_entry.value > range[0]
|
104
|
+
end
|
105
|
+
|
106
|
+
# Give RangeList iterative ability.
|
107
|
+
# @yield [range_start, range_end] give the range element to the block
|
108
|
+
def each(&block)
|
109
|
+
if block
|
110
|
+
# Iterating an empty tree will raise an error,
|
111
|
+
# see https://github.com/davidkellis/treemap/issues/1
|
112
|
+
tree.empty? ? self : tree.each(&block)
|
113
|
+
else
|
114
|
+
enum_for(:each)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# @!visibility private
|
119
|
+
def inspect
|
120
|
+
to_a.inspect
|
121
|
+
end
|
122
|
+
|
123
|
+
# Return the current range as an array.
|
124
|
+
# @return [Array]
|
125
|
+
def to_a
|
126
|
+
tree.empty? ? [] : tree.to_a
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
attr_reader :tree
|
132
|
+
|
133
|
+
def validate_range!(range)
|
134
|
+
raise ArgumentError, "`range` should be `Array` type." unless range.is_a?(Array)
|
135
|
+
raise ArgumentError, "`range` size should be equal to 2." unless range.size == 2
|
136
|
+
raise ArgumentError, "All elements of `range` should be `Integer`." unless range.all? { |item| item.is_a?(Integer) }
|
137
|
+
end
|
138
|
+
|
139
|
+
def empty_range?(range)
|
140
|
+
range[0] >= range[1]
|
141
|
+
end
|
8
142
|
end
|
data/range_list.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
|
19
19
|
spec.metadata["homepage_uri"] = spec.homepage
|
20
20
|
spec.metadata["source_code_uri"] = "https://gitlab.com/songhuangcn/range_list"
|
21
|
+
spec.metadata["documentation_uri"] = "https://rubydoc.info/gems/range_list"
|
21
22
|
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
22
23
|
|
23
24
|
# Specify which files should be added to the gem when it is released.
|
@@ -33,6 +34,7 @@ Gem::Specification.new do |spec|
|
|
33
34
|
|
34
35
|
# Uncomment to register a new dependency of your gem
|
35
36
|
# spec.add_dependency "example-gem", "~> 1.0"
|
37
|
+
spec.add_dependency "treemap", "~> 1.0"
|
36
38
|
|
37
39
|
# For more information and examples about making a new gem, check out our
|
38
40
|
# guide at: https://bundler.io/guides/creating_gem.html
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: range_list
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Song Huang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-02-
|
12
|
-
dependencies:
|
11
|
+
date: 2022-02-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: treemap
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
13
27
|
description:
|
14
28
|
email:
|
15
29
|
- songhuangcn@gmail.com
|
@@ -18,19 +32,21 @@ extensions: []
|
|
18
32
|
extra_rdoc_files: []
|
19
33
|
files:
|
20
34
|
- Gemfile
|
35
|
+
- Gemfile.lock
|
21
36
|
- LICENSE.txt
|
22
37
|
- README.md
|
23
38
|
- Rakefile
|
24
39
|
- lib/range_list.rb
|
40
|
+
- lib/range_list/errors.rb
|
25
41
|
- lib/range_list/version.rb
|
26
42
|
- range_list.gemspec
|
27
|
-
- sig/range_list.rbs
|
28
43
|
homepage: https://gitlab.com/songhuangcn/range_list
|
29
44
|
licenses:
|
30
45
|
- MIT
|
31
46
|
metadata:
|
32
47
|
homepage_uri: https://gitlab.com/songhuangcn/range_list
|
33
48
|
source_code_uri: https://gitlab.com/songhuangcn/range_list
|
49
|
+
documentation_uri: https://rubydoc.info/gems/range_list
|
34
50
|
post_install_message:
|
35
51
|
rdoc_options: []
|
36
52
|
require_paths:
|
data/sig/range_list.rbs
DELETED