range_list 1.2.0 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3bbec9e50fbfcf613d6371f9851c1410269819c738d362bbe0db73bf6ab1ed6
4
- data.tar.gz: 48b42d5f37e67577cc92528b4f3e898b58f81f7781fa4ea388347572fb70d90a
3
+ metadata.gz: 7ea59292d297f5583f7a9ceddaf8194cbd33704180c3e43f15fe87358c8d02d5
4
+ data.tar.gz: f8ea601a80d2261c1b869aa57699bd0c71d048b4a94b25b978d67d1636d426b5
5
5
  SHA512:
6
- metadata.gz: c6f784320a3ab3b9b1c7714c9c7350aef3824b222a28ca0b1278722a728564b91c6c40faf3bbb8ea8a2926795daa56ca8f3db740cec6fd8833371bb60214ddd8
7
- data.tar.gz: 98c20d0456e3c84432dfa9d3d09438c4887606dead589cfb1006407569b3c7f1330e0e3401fba5562b0c1c0c3dba408ad43fa0ea18f99232775ce7dcef69c3ee
6
+ metadata.gz: 52b7dd400bb94273b9e0ff1702db7d5bd328f88e425322ba3838cc859e4629f0f5f2776bcedec7f73ba90ca0936b8f661fd435bde89bf67bbfdede88c93f62b5
7
+ data.tar.gz: af2aee3e2b4c37cdffbe89518423ea037b3348db50c9bfeff3b27259f6ff54f055265c3cbfb7c5ec7a9bc7410baa475e1d2f59be0259a5061b2e5197bd8e7280
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- range_list (1.2.0)
4
+ range_list (1.3.0)
5
5
  rbtree (~> 0.4.5)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -10,7 +10,6 @@ RangeList use AVL Tree processing internally, so range operations are very fast.
10
10
  [![Gem Version](https://badge.fury.io/rb/range_list.svg)](https://rubygems.org/gems/range_list)
11
11
  [![Documentation](https://img.shields.io/badge/docs-YARD-blue.svg)](https://rubydoc.info/gems/range_list)
12
12
  [![pipeline status](https://gitlab.com/songhuangcn/range_list/badges/main/pipeline.svg)](https://gitlab.com/songhuangcn/range_list/-/commits/main)
13
- [![coverage report](https://gitlab.com/songhuangcn/range_list/badges/main/coverage.svg)](https://gitlab.com/songhuangcn/range_list/-/commits/main)
14
13
 
15
14
  ## Installation
16
15
 
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RangeList
4
+ # @!visibility private
5
+ module AvlTree
6
+ class AbstractAdapter
7
+ def put(key, value)
8
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
9
+ end
10
+
11
+ def lower_entry(key)
12
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
13
+ end
14
+
15
+ def sub_map(from_key, to_key)
16
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
17
+ end
18
+
19
+ def remove(key)
20
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
21
+ end
22
+
23
+ def each(&block)
24
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rbtree"
4
+ require_relative "abstract_adapter"
5
+
6
+ class RangeList
7
+ # @!visibility private
8
+ module AvlTree
9
+ class RBTreeAdapter < AbstractAdapter
10
+ def initialize
11
+ @rbtree = RBTree.new
12
+ end
13
+
14
+ def put(key, value)
15
+ rbtree[key] = value
16
+ end
17
+
18
+ def lower_entry(key)
19
+ rbtree.upper_bound(key)
20
+ end
21
+
22
+ def sub_map(from_key, to_key)
23
+ rbtree.bound(from_key, to_key).to_a
24
+ end
25
+
26
+ def remove(key)
27
+ rbtree.delete(key)
28
+ end
29
+
30
+ def each(&block)
31
+ rbtree.each(&block)
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :rbtree
37
+ end
38
+ end
39
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class RangeList
4
- VERSION = "1.2.0"
4
+ VERSION = "1.3.0"
5
5
  end
data/lib/range_list.rb CHANGED
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rbtree"
4
3
  require_relative "range_list/version"
5
4
  require_relative "range_list/errors"
5
+ require_relative "range_list/avl_tree/rbtree_adapter"
6
6
 
7
7
  class RangeList
8
8
  include Enumerable
9
9
 
10
10
  def initialize
11
- @tree = RBTree.new
11
+ @avl_tree = AvlTree::RBTreeAdapter.new
12
12
  end
13
13
 
14
14
  # Add range into current range list.
@@ -23,27 +23,27 @@ class RangeList
23
23
  return self if empty_range?(range)
24
24
 
25
25
  # Get real range start.
26
- start_floor_entry = tree.upper_bound(range[0])
27
- range_start = if !start_floor_entry.nil? && start_floor_entry[1] >= range[0]
28
- start_floor_entry[0]
26
+ start_lower_range = avl_tree.lower_entry(range[0])
27
+ range_start = if !start_lower_range.nil? && start_lower_range[1] >= range[0]
28
+ start_lower_range[0]
29
29
  else
30
30
  range[0]
31
31
  end
32
32
 
33
33
  # Get real range end.
34
- end_floor_entry = tree.upper_bound(range[1])
35
- range_end = if !end_floor_entry.nil? && end_floor_entry[1] >= range[1]
36
- end_floor_entry[1]
34
+ end_lower_range = avl_tree.lower_entry(range[1])
35
+ range_end = if !end_lower_range.nil? && end_lower_range[1] >= range[1]
36
+ end_lower_range[1]
37
37
  else
38
38
  range[1]
39
39
  end
40
40
 
41
41
  # Insert or replace new range.
42
- tree[range_start] = range_end
42
+ avl_tree.put(range_start, range_end)
43
43
 
44
44
  # Remove keys between range, exclude start, include end.
45
- between_maps = tree.bound(range[0] + 1, range[1])
46
- between_maps.to_a.each { |key, _value| tree.delete(key) }
45
+ sub_range = avl_tree.sub_map(range[0] + 1, range[1])
46
+ sub_range.each { |range_start, _range_end| avl_tree.remove(range_start) }
47
47
 
48
48
  self
49
49
  end
@@ -58,21 +58,21 @@ class RangeList
58
58
  # Return when range is empty.
59
59
  return self if empty_range?(range)
60
60
 
61
- # Insert end lower entry
62
- end_lower_entry = tree.upper_bound(range[1] - 1)
63
- if !end_lower_entry.nil? && end_lower_entry[1] > range[1]
64
- tree[range[1]] = end_lower_entry[1]
61
+ # Insert end lower range, `-1` means not include.
62
+ end_lower_range = avl_tree.lower_entry(range[1] - 1)
63
+ if !end_lower_range.nil? && end_lower_range[1] > range[1]
64
+ avl_tree.put(range[1], end_lower_range[1])
65
65
  end
66
66
 
67
- # Relace start lower entry
68
- start_lower_entry = tree.upper_bound(range[0] - 1)
69
- if !start_lower_entry.nil? && start_lower_entry[1] > range[0]
70
- tree[start_lower_entry[0]] = range[0]
67
+ # Relace start lower range, `-1` means not include.
68
+ start_lower_range = avl_tree.lower_entry(range[0] - 1)
69
+ if !start_lower_range.nil? && start_lower_range[1] > range[0]
70
+ avl_tree.put(start_lower_range[0], range[0])
71
71
  end
72
72
 
73
73
  # Remove keys between range, include start, exclude end
74
- between_maps = tree.bound(range[0], range[1] - 1)
75
- between_maps.to_a.each { |key, _value| tree.delete(key) }
74
+ sub_range = avl_tree.sub_map(range[0], range[1] - 1)
75
+ sub_range.each { |range_start, _range_end| avl_tree.remove(range_start) }
76
76
 
77
77
  self
78
78
  end
@@ -80,7 +80,8 @@ class RangeList
80
80
  # Print current range list.
81
81
  # @return [void]
82
82
  def print
83
- puts map { |k, v| "[#{k}, #{v})" }.join(" ")
83
+ info = map { |k, v| "[#{k}, #{v})" }.join(" ")
84
+ puts info
84
85
  end
85
86
 
86
87
  # Returns true if current ranges contains all elements of the range.
@@ -94,8 +95,8 @@ class RangeList
94
95
  # Return false when range is empty.
95
96
  return false if empty_range?(range)
96
97
 
97
- start_floor_entry = tree.upper_bound(range[0])
98
- !start_floor_entry.nil? && start_floor_entry[1] >= range[1]
98
+ start_lower_range = avl_tree.lower_entry(range[0])
99
+ !start_lower_range.nil? && start_lower_range[1] >= range[1]
99
100
  end
100
101
 
101
102
  # Returns true if current ranges contains any element of the range.
@@ -109,8 +110,9 @@ class RangeList
109
110
  # Return false when range is empty.
110
111
  return false if empty_range?(range)
111
112
 
112
- end_lower_entry = tree.upper_bound(range[1] - 1)
113
- !end_lower_entry.nil? && end_lower_entry[1] > range[0]
113
+ # `-1` means not include.
114
+ end_lower_range = avl_tree.lower_entry(range[1] - 1)
115
+ !end_lower_range.nil? && end_lower_range[1] > range[0]
114
116
  end
115
117
 
116
118
  # Returns true if current ranges contains the element.
@@ -120,15 +122,15 @@ class RangeList
120
122
  def contains?(element)
121
123
  raise ArgumentError, "`element` should be `Integer` type." unless element.is_a?(Integer)
122
124
 
123
- floor_entry = tree.upper_bound(element)
124
- !floor_entry.nil? && floor_entry[1] > element
125
+ lower_entry = avl_tree.lower_entry(element)
126
+ !lower_entry.nil? && lower_entry[1] > element
125
127
  end
126
128
 
127
129
  # Give RangeList iterative ability.
128
130
  # @yield [range_start, range_end] give the range element to the block
129
131
  def each(&block)
130
132
  if block
131
- tree.each(&block)
133
+ avl_tree.each(&block)
132
134
  else
133
135
  enum_for(:each)
134
136
  end
@@ -141,7 +143,7 @@ class RangeList
141
143
 
142
144
  private
143
145
 
144
- attr_reader :tree
146
+ attr_reader :avl_tree
145
147
 
146
148
  def validate_range!(range)
147
149
  raise ArgumentError, "`range` should be `Array` type." unless range.is_a?(Array)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: range_list
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.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-26 00:00:00.000000000 Z
11
+ date: 2022-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbtree
@@ -37,6 +37,8 @@ files:
37
37
  - README.md
38
38
  - Rakefile
39
39
  - lib/range_list.rb
40
+ - lib/range_list/avl_tree/abstract_adapter.rb
41
+ - lib/range_list/avl_tree/rbtree_adapter.rb
40
42
  - lib/range_list/errors.rb
41
43
  - lib/range_list/version.rb
42
44
  - range_list.gemspec