ranges_merger 0.0.0 → 0.1.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.
data/README.rdoc CHANGED
@@ -4,7 +4,9 @@ Very simple gem for merging range-like objects.
4
4
 
5
5
  == How to use
6
6
 
7
- At this moment...
7
+ Please use range-like object converted to format [[from, to], [from, to], ...].
8
+
9
+ If you want to merge 2 ranges please use code just like below.
8
10
 
9
11
  a = [1, 3]
10
12
 
@@ -14,6 +16,40 @@ At this moment...
14
16
 
15
17
  # => result = [[1, 4]]
16
18
 
19
+
20
+
21
+ If you want to merge more than 2 ranges please use code just like below.
22
+
23
+ a = [1, 3]
24
+
25
+ b = [2, 4]
26
+
27
+ c = [4, 6]
28
+
29
+ result = RangesMerger.merge([a, b, c])
30
+
31
+ # => result = [[1, 6]]
32
+
33
+
34
+
35
+ If you want to merge Range objects.
36
+
37
+ ranges = [
38
+
39
+ (1..2),
40
+
41
+ (2..3),
42
+
43
+ (5..8)
44
+
45
+ ]
46
+
47
+ result = RangesMerger.merge(ranges)
48
+
49
+ # => result = [(1..3),(5..8)]
50
+
51
+
52
+
17
53
  == Contributing to ranges_merger
18
54
 
19
55
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
data/Rakefile CHANGED
@@ -18,7 +18,7 @@ Jeweler::Tasks.new do |gem|
18
18
  gem.homepage = "http://github.com/akwiatkowski/ranges_merger"
19
19
  gem.license = "LPGLv3"
20
20
  gem.summary = %Q{Small gem for merging range-like objects}
21
- gem.description = %Q{Simple gem used for merging range-like objects}
21
+ gem.description = %Q{Simple gem used for merging range-like objects. If you have problems with operations on ranges this gem can save you some time.}
22
22
  gem.email = "bobikx@poczta.fm"
23
23
  gem.authors = ["Aleksander Kwiatkowski"]
24
24
  # dependencies defined in Gemfile
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.1.0
data/lib/ranges_merger.rb CHANGED
@@ -1,31 +1,98 @@
1
1
  class RangesMerger
2
+
3
+ # Merge for various objects (Array, Range)
4
+ def self.merge(_array)
5
+ klass = _array.first.class
6
+
7
+ if klass.to_s == "Array"
8
+ return self.merge_loop(_array)
9
+ elsif klass.to_s == "Range"
10
+ result = self.merge_loop( _array.collect{|a| [a.first, a.last]} )
11
+ return result.collect{|r| Range.new(r[0], r[1])}
12
+ else
13
+ return []
14
+ end
15
+
16
+ end
17
+
18
+ # Merge loop
19
+ def self.merge_loop(_array)
20
+ before = _array
21
+ while true do
22
+ after = self.merge_array(_array)
23
+ return after if before == after or not check_overlaps(after)
24
+ before = after
25
+ end
26
+ end
27
+
28
+ def self.merge_array(_array)
29
+ return _array if _array.size <= 1
30
+ sorted = _array.sort { |a, b| a[0] <=> b[0] }.uniq
31
+
32
+ i = 1
33
+ while i < sorted.size do
34
+ to_merge = [sorted[i-1], sorted[i]]
35
+ # puts "merging #{to_merge.inspect}"
36
+
37
+ result = self.two_way_merge(to_merge)
38
+ # puts "merged #{result.inspect}"
39
+
40
+ sorted[i-1] = result[0]
41
+
42
+ if result.size == 1
43
+ sorted[i] = nil
44
+ sorted.delete_if { |s| s.nil? }
45
+ else
46
+ i += 1
47
+ end
48
+ end
49
+
50
+ return sorted
51
+ end
52
+
53
+ # Check if there are overlaps in Array
54
+ def self.check_overlaps(_array)
55
+ sorted = _array.sort { |a, b| a[0] <=> b[0] }.uniq
56
+
57
+ (1...sorted.size).each do |i|
58
+ return true if sorted[i][0] <= sorted[i-1][0]
59
+ return true if sorted[i][0] <= sorted[i-1][1]
60
+ end
61
+ return false
62
+ end
63
+
2
64
  def self.two_way_merge(_array)
3
65
  a_from = _array[0][0]
4
66
  b_from = _array[1][0]
5
67
  a_to = _array[0][1]
6
68
  b_to = _array[1][1]
7
69
 
8
- # 1. outside each other
9
- if (a_to < b_to and a_from < b_from and a_to < b_from) or (a_to > b_to and a_from > b_from and b_to < a_from)
70
+ # 1A. outside each other A > B
71
+ if (a_to < b_to and a_from < b_from and a_to < b_from)
10
72
  return [[a_from, a_to], [b_from, b_to]]
11
73
  end
12
74
 
13
- # 2. A is inside B
75
+ # 1B. outside each other B > A
76
+ if (a_to > b_to and a_from > b_from and b_to < a_from)
77
+ return [[b_from, b_to], [a_from, a_to]]
78
+ end
79
+
80
+ # 2A. A is inside B
14
81
  if a_from >= b_from and a_to <= b_to
15
82
  return [[b_from, b_to]]
16
83
  end
17
84
 
18
- # 3. B is inside A
85
+ # 2B. B is inside A
19
86
  if b_from >= a_from and b_to <= a_to
20
87
  return [[a_from, a_to]]
21
88
  end
22
89
 
23
- # 4. overlapping, A < B
90
+ # 3A. overlapping, A < B
24
91
  if a_from < b_from and a_to < b_to and a_to >= b_from
25
92
  return [[a_from, b_to]]
26
93
  end
27
94
 
28
- # 4. overlapping, B < A
95
+ # 3B. overlapping, B < A
29
96
  if b_from < a_from and b_to < a_to and b_to >= a_from
30
97
  return [[b_from, a_to]]
31
98
  end
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "ranges_merger"
8
- s.version = "0.0.0"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Aleksander Kwiatkowski"]
12
12
  s.date = "2011-12-04"
13
- s.description = "Simple gem used for merging range-like objects"
13
+ s.description = "Simple gem used for merging range-like objects. If you have problems with operations on ranges this gem can save you some time."
14
14
  s.email = "bobikx@poczta.fm"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.txt",
@@ -1,31 +1,149 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "RangesMerger" do
4
- it "should merge 2 overlapping" do
4
+ it "should merge 2 overlapping ranges" do
5
5
  a = [1, 3]
6
6
  b = [2, 4]
7
7
  result = RangesMerger.two_way_merge([a, b])
8
8
  result.should == [[1, 4]]
9
9
  end
10
10
 
11
- it "should merge 2 not overlapping" do
11
+ it "should merge 2 overlapping ranges" do
12
+ a = [2, 4]
13
+ b = [1, 3]
14
+ result = RangesMerger.two_way_merge([a, b])
15
+ result.should == [[1, 4]]
16
+ end
17
+
18
+ it "should merge 2 not overlapping ranges" do
19
+ b = [1, 3]
20
+ a = [5, 6]
21
+ # it sorts :)
22
+ result = RangesMerger.two_way_merge([a, b])
23
+ result.should == [[1, 3], [5, 6]]
24
+ result.should_not == [[5, 6], [1, 3]]
25
+ end
26
+
27
+ it "should merge 2 not overlapping ranges" do
12
28
  a = [1, 3]
13
29
  b = [5, 6]
14
30
  result = RangesMerger.two_way_merge([a, b])
15
31
  result.should == [[1, 3], [5, 6]]
16
32
  end
17
33
 
18
- it "should merge 2 identical" do
34
+ it "should merge 2 identical ranges" do
19
35
  a = [1, 2]
20
36
  b = [1, 2]
21
37
  result = RangesMerger.two_way_merge([a, b])
22
38
  result.should == [[1, 2]]
23
39
  end
24
40
 
25
- it "should merge 2 overlapping" do
26
- a = [2, 4]
27
- b = [1, 3]
41
+ it "should merge 2 ranges, A within B" do
42
+ a = [1, 5]
43
+ b = [2, 3]
44
+ result = RangesMerger.two_way_merge([a, b])
45
+ result.should == [[1, 5]]
46
+ end
47
+
48
+ it "should merge 2 ranges, B within A" do
49
+ b = [1, 5]
50
+ a = [2, 3]
28
51
  result = RangesMerger.two_way_merge([a, b])
52
+ result.should == [[1, 5]]
53
+ end
54
+
55
+ it "should merge 3 ranges (simple)" do
56
+ ranges = [[1, 2], [2, 3], [3, 4]]
57
+ result = RangesMerger.merge(ranges)
29
58
  result.should == [[1, 4]]
30
59
  end
60
+
61
+ it "should merge multiple (1)" do
62
+ ranges = [[0, 3], [3, 4], [1, 2], [10, 14], [12, 13]]
63
+ result = RangesMerger.merge(ranges)
64
+ result.should == [[0, 4], [10, 14]]
65
+ end
66
+
67
+ it "should merge multiple (2)" do
68
+ ranges = [
69
+ [2, 4],
70
+ [3, 5],
71
+ [6, 9],
72
+ [7, 8],
73
+ [8, 9]
74
+ ]
75
+ result = RangesMerger.merge(ranges)
76
+ result.should == [[2, 5], [6, 9]]
77
+ end
78
+
79
+
80
+ it "should merge multiple (3)" do
81
+ ranges = [
82
+ [2, 10],
83
+ [3, 9],
84
+ [4, 8],
85
+ [5, 7],
86
+ [6, 6]
87
+ ]
88
+ result = RangesMerger.merge(ranges)
89
+ result.should == [[2, 10]]
90
+ end
91
+
92
+
93
+ it "should merge multiple (3)" do
94
+ ranges = [
95
+ [1, 100],
96
+ [2, 200],
97
+ [3, 500],
98
+ [200, 201],
99
+ [100, 2001]
100
+ ]
101
+ result = RangesMerger.merge(ranges)
102
+ result.should == [[1, 2001]]
103
+ end
104
+
105
+ it "should do the readme code" do
106
+ a = [1, 3]
107
+ b = [2, 4]
108
+ result = RangesMerger.two_way_merge([a, b])
109
+ result.should == [[1, 4]]
110
+
111
+ a = [1, 3]
112
+ b = [2, 4]
113
+ c = [4, 6]
114
+ result = RangesMerger.merge([a, b, c])
115
+ result.should == [[1, 6]]
116
+ end
117
+
118
+ it "should merge very big array" do
119
+ ranges = Array.new
120
+ (1..1000).each do |i|
121
+ ranges << [i, i + 10]
122
+ end
123
+ result = RangesMerger.merge(ranges)
124
+ result.should == [[1, 1000 + 10]]
125
+ end
126
+
127
+ it "should merge very big array (2)" do
128
+ ranges = Array.new
129
+ (1..1000).each do |i|
130
+ ranges << [10*i, 10*i + 1]
131
+ end
132
+ result = RangesMerger.merge(ranges)
133
+ result.size.should == 1000
134
+ result[0][0].should == 10
135
+ result.last[1].should == 1000*10 + 1
136
+ end
137
+
138
+ it "should merge Range objects" do
139
+ ranges = [
140
+ (1..2),
141
+ (2..3),
142
+ (5..8)
143
+ ]
144
+ result = RangesMerger.merge(ranges)
145
+ result.should == [(1..3),(5..8)]
146
+ end
147
+
148
+
31
149
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ranges_merger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-12-04 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &78403210 !ruby/object:Gem::Requirement
16
+ requirement: &75213000 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.3.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *78403210
24
+ version_requirements: *75213000
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &78402960 !ruby/object:Gem::Requirement
27
+ requirement: &75212750 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *78402960
35
+ version_requirements: *75212750
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: jeweler
38
- requirement: &78402700 !ruby/object:Gem::Requirement
38
+ requirement: &75212470 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.6.4
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *78402700
46
+ version_requirements: *75212470
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rcov
49
- requirement: &78402440 !ruby/object:Gem::Requirement
49
+ requirement: &75212230 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,8 +54,9 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *78402440
58
- description: Simple gem used for merging range-like objects
57
+ version_requirements: *75212230
58
+ description: Simple gem used for merging range-like objects. If you have problems
59
+ with operations on ranges this gem can save you some time.
59
60
  email: bobikx@poczta.fm
60
61
  executables: []
61
62
  extensions: []
@@ -91,7 +92,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
92
  version: '0'
92
93
  segments:
93
94
  - 0
94
- hash: -24009951
95
+ hash: 63330927
95
96
  required_rubygems_version: !ruby/object:Gem::Requirement
96
97
  none: false
97
98
  requirements: