range_list 1.2.0 → 1.3.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: 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