range_list_barry 0.0.1

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/range_list.rb +111 -0
  3. metadata +43 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b4305219593ab7b1dd9998ed1a9e6211663a3cc38c21afc830e1504ea5b6228b
4
+ data.tar.gz: e476b3a3549bdbe246bb1562d2f186cede26bb81f0e9ab279597953ee9f7d1f3
5
+ SHA512:
6
+ metadata.gz: 65050613f0354ac69fc77eae564396fe5f1eef78996095a71138e7b6a2d98765daa2554dc6300972e87c1c40e8cbb9e2684a272eef4c9cb05f868611776d6f27
7
+ data.tar.gz: e8ab26c327ac65cc37b29856f37dd5ece2758cf69bebe63f88d4de50ea5db8071781e4f1c530905e3eae660cf5dfd17fc4ca469c50bdc92ef0e39fd521ce4977
data/lib/range_list.rb ADDED
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/range_list/intersection'
4
+ require './lib/range_list/verify_range'
5
+
6
+ ##
7
+ # A pair of integers define a range, for example: [1, 5). This range includes integers: 1, 2, 3, and 4.
8
+ # A range list is an aggregate of these ranges: [1, 5), [10, 11), [100, 201)
9
+ class RangeList
10
+ attr_reader :range_list
11
+
12
+ def initialize
13
+ @range_list = {}
14
+ end
15
+
16
+ # @param [Array<Integer>] range
17
+ # @return [Hash] return the sorted hash representation of the range list.
18
+ def add(range)
19
+ veryify_range!(range)
20
+
21
+ # we need to modify the value in the hash, so disable HashEachMethods cop.
22
+ # rubocop:disable Style/HashEachMethods
23
+ @range_list.keys.each do |key|
24
+ intersection = intersection(range, [key, @range_list[key]])
25
+ next unless intersection
26
+
27
+ # 增加新的range时, 如果有交集, 则需要将交集的range更新为[min, max]
28
+ min = [key, range[0]].min
29
+ @range_list[min] = @range_list.delete(key)
30
+
31
+ max = [@range_list[min], range[1]].max
32
+ @range_list[min] = max
33
+ return remove_overlapped_range
34
+ end
35
+ # rubocop:enable Style/HashEachMethods
36
+
37
+ # when no intersection, insert to hash
38
+ insert(range)
39
+ end
40
+
41
+ # rubocop:disable Style/HashEachMethods
42
+ # rubocop:disable Metrics/AbcSize
43
+ #
44
+ # @param [Array<Integer>] range
45
+ # @return [Hash] return the sorted hash representation of the range list
46
+ def remove(range)
47
+ veryify_range!(range)
48
+
49
+ @range_list.keys.each do |key|
50
+ intersection = intersection(range, [key, @range_list[key]])
51
+ next unless intersection&.max # an intersecion might not has max becuase the range[0] = range[1]
52
+
53
+ # 如果intersection.min == key, 则需要删除key, 创建新的hash {intersection.max => @range_list[key]}
54
+ # 如果intersection.min > key, 则需要删除key, 创建更新hash {key => intersection.min}
55
+ # 如果value > intersection.max, 则需要创建更新hash {intersection.max => value}
56
+ @range_list[intersection.max] = @range_list[key] if @range_list[key] > intersection.max
57
+
58
+ if intersection.min == key
59
+ @range_list[intersection.max] = @range_list.delete(key)
60
+ elsif intersection.min > key
61
+ @range_list[key] = intersection.min
62
+ end
63
+ end
64
+
65
+ sorted_range_list
66
+ end
67
+ # rubocop:enable Style/HashEachMethods
68
+ # rubocop:enable Metrics/AbcSize
69
+
70
+ ##
71
+ # Print all the ranges in format: [1, 5) [10, 20)
72
+ def print
73
+ str = ''
74
+ sorted_range_list.each do |key, value|
75
+ str += "[#{key}, #{value}) " unless key == value
76
+ end
77
+ puts str
78
+ end
79
+
80
+ # @return [String] return all the ranges in hash format
81
+ def inspect
82
+ sorted_range_list
83
+ end
84
+
85
+ private
86
+
87
+ # @params [Array<Integer>] range
88
+ # insert the range to range_list hash
89
+ def insert(range)
90
+ @range_list[range[0]] = range[1]
91
+ sorted_range_list
92
+ end
93
+
94
+ def sorted_range_list
95
+ @range_list.sort.to_h.reject { |key, value| key == value }
96
+ end
97
+
98
+ def remove_overlapped_range
99
+ return sorted_range_list if @range_list.length == 1
100
+
101
+ groups = @range_list.sort.map { |key, value| [key, value] }
102
+
103
+ # only need to iterate to the second last group, because we know the last group is not overlapped
104
+ groups[0..-2].each_with_index do |group, i|
105
+ groups.delete_at(i + 1) if group[1] > groups[i + 1][0]
106
+ end
107
+ @range_list = groups.to_h
108
+
109
+ sorted_range_list
110
+ end
111
+ end
metadata ADDED
@@ -0,0 +1,43 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: range_list_barry
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - uooobarry
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-06-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple range list gem
14
+ email: huahua.personal@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/range_list.rb
20
+ homepage: https://jihulab.com/UoooBarry/rangelist
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubygems_version: 3.3.3
40
+ signing_key:
41
+ specification_version: 4
42
+ summary: Ruby implementation of range list.
43
+ test_files: []