ranges_merger 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: