range_list 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60084bab9a2a689bd360d45fbd94f6915159f20779edfa4137758f5c29bb6e89
4
- data.tar.gz: 897265da656540c840314e498cc4bb792f0a384c54cc3f27f62a42506a8d5b1b
3
+ metadata.gz: f27b8cd8551942e4ff09f2cc32c525e7fd5724cdbea8e322203cd01df681fb46
4
+ data.tar.gz: c24ffbe52e439561c2010fccdf67f68d9700703b23c4ed45d34c143ba5e6de46
5
5
  SHA512:
6
- metadata.gz: db4e3df7dc8e9be8da2c490050d3fd8b9f4b0b58f88581a32ca788d54b53fdef9f2d4a1d1d4bacacc22f7bdcdf095e4749240afe8b6b25e69b5963f45cc76d2e
7
- data.tar.gz: b8d0050152b5ac4221b41fc9223a845be3c8636d70a85a204c9e7bad455f155f3aa119ea0e635eb71982015918449de1da062d89ad8c8f30acf7e845769a3502
6
+ metadata.gz: 62a1a66f4607c3e17424d8bd76cd8371626e8ff0d64961f189f09534fb33cc6e60537e821b3bb743389057db0c76a4e5e83cd7cbe8d3a6872c6c808891237f16
7
+ data.tar.gz: 9fb515423d8048f124e15a88cb3c5b718e7d273694bb8e9fe128ce2e37ebda636ba1da330af406abfc57d8566686fa71eff91d88c7af1eee55cd9b5b4ad75ad1
data/Gemfile CHANGED
@@ -8,3 +8,11 @@ gemspec
8
8
  gem "rake", "~> 13.0"
9
9
 
10
10
  gem "minitest", "~> 5.0"
11
+
12
+ gem "standard", "~> 1.7"
13
+
14
+ gem "yard", "~> 0.9.27"
15
+
16
+ gem "simplecov", "~> 0.21.2"
17
+
18
+ gem "simplecov-cobertura", "~> 2.1"
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
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/range_list`. To experiment with that code, run `bin/console` for an interactive prompt.
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
- TODO: Delete this and the text above, and describe your gem
6
+ RangeList offers `add`, `remove`, `print`, `containsAll?`, `containsAny?` methods, and offers the `Enumerable` ability,
7
+ you can handle ranges more easily.
8
+
9
+ [![Gem Version](https://badge.fury.io/rb/range_list.svg)](https://rubygems.org/gems/range_list)
10
+ [![Documentation](https://img.shields.io/badge/docs-YARD-blue.svg)](https://rubydoc.info/gems/range_list)
11
+ [![pipeline status](https://gitlab.com/songhuangcn/range_list/badges/main/pipeline.svg)](https://gitlab.com/songhuangcn/range_list/-/commits/main)
12
+ [![coverage report](https://gitlab.com/songhuangcn/range_list/badges/main/coverage.svg)](https://gitlab.com/songhuangcn/range_list/-/commits/main)
6
13
 
7
14
  ## Installation
8
15
 
9
- Add this line to your application's Gemfile:
16
+ Add gem to your application's Gemfile:
10
17
 
11
- ```ruby
12
- gem 'range_list'
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
- $ gem install range_list
24
+ ```shell
25
+ gem install range_list
26
+ ```
22
27
 
23
28
  ## Usage
24
29
 
25
- TODO: Write usage instructions here
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 pull requests are welcome on GitHub at https://github.com/[USERNAME]/range_list.
64
+ Bug reports and Merge requests are welcome on GitLab at https://gitlab.com/songhuangcn/range_list.
36
65
 
37
66
  ## License
38
67
 
@@ -0,0 +1,7 @@
1
+ class RangeList
2
+ # RangeList base error.
3
+ class Error < StandardError; end
4
+
5
+ # When the error raised, you should see the doc and check your argument.
6
+ class ArgumentError < Error; end
7
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RangeList
4
- VERSION = "0.1.0"
3
+ class RangeList
4
+ VERSION = "1.0.0"
5
5
  end
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
- module RangeList
6
- class Error < StandardError; end
7
- # Your code goes here...
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: 0.1.0
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-25 00:00:00.000000000 Z
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
@@ -1,4 +0,0 @@
1
- module RangeList
2
- VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
- end