sorted_array_binary 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+ Gemfile.lock
15
+
16
+ # YARD artifacts
17
+ .yardoc
18
+ _yardoc
19
+ doc/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ - "jruby-19mode"
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
6
+ gem 'coveralls', :require => false
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Dmitry Maksyoma
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ sorted_array_binary
2
+ ===================
3
+
4
+ [![Build Status](https://travis-ci.org/ledestin/sorted_array_binary.png)](https://travis-ci.org/ledestin/sorted_array_binary)
5
+ [![Coverage Status] (https://coveralls.io/repos/ledestin/sorted_array_binary/badge.png)] (https://coveralls.io/r/ledestin/sorted_array_binary)
6
+ [![Code Climate](https://codeclimate.com/github/ledestin/sorted_array_binary.png)](https://codeclimate.com/github/ledestin/sorted_array_binary)
7
+
8
+ A sorted array using binary search
9
+
10
+ ## Why
11
+
12
+ 1. Neither of the existing sorted arrays gems use binary search (i.e. slow or
13
+ very slow).
14
+ 2. I don't like their source code, so I decided to roll my own, instead of
15
+ contributing.
16
+
17
+ Existing sorted array gems as of Jan 2014:
18
+ * sorted_array (0.0.5)
19
+ * array-sorted (1.1.2)
20
+
21
+ ## Example
22
+
23
+ ```ruby
24
+ require 'sorted_array_binary'
25
+
26
+ # Use standard sorting via <=>.
27
+ array = SortedArrayBinary.new
28
+ array.push 'b', 'a' #=> ['a', 'b']
29
+
30
+ # Use custom sorting block.
31
+ array = SortedArrayBinary.new { |a, b| b <=> a }
32
+ array.push 'a', 'b' #=> ['b', 'a']
33
+ ```
34
+
35
+ ## Performance
36
+
37
+ When #push'ing 1000 random numbers into an array:
38
+ ```
39
+ sorted_array (0.0.5) 1.179088
40
+ array-sorted (1.1.2) 0.076348
41
+ sorted_array_binary (0.0.1) 0.015969
42
+ ```
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new
6
+ task :default => :spec
7
+
8
+ task :gem do
9
+ system 'gem build *.gemspec'
10
+ end
@@ -0,0 +1,216 @@
1
+ # Copyright (C) 2014 by Dmitry Maksyoma <ledestin@gmail.com>
2
+
3
+ # Automatically sorted array (by using binary search). Nils aren't allowed.
4
+ # Methods that reorder elements are not implemented, as well as #[]= and #fill.
5
+ #
6
+ # = Example
7
+ # require 'sorted_array_binary'
8
+ #
9
+ # # Use standard sorting via <=>.
10
+ # array = SortedArrayBinary.new
11
+ # array.push 'b', 'a' #=> ['a', 'b']
12
+ #
13
+ # # Use custom sorting block.
14
+ # array = SortedArrayBinary.new { |a, b| b <=> a }
15
+ # array.push 'a', 'b' #=> ['b', 'a']
16
+ class SortedArrayBinary < Array
17
+ # {{{2 ComparisonState
18
+ class ComparisonState #:nodoc:
19
+ def initialize state
20
+ raise ArgumentError, "invalid state: #{state.inspect}" \
21
+ unless state && state >= -1 && state <= 1
22
+
23
+ @state = state
24
+ end
25
+
26
+ def equal?
27
+ @state == 0
28
+ end
29
+
30
+ def greater?
31
+ @state == 1
32
+ end
33
+
34
+ def less?
35
+ @state == -1
36
+ end
37
+ end
38
+ # }}}2
39
+
40
+ class InvalidSortBlock < RuntimeError #:nodoc:
41
+ end
42
+
43
+ def self._check_for_nil *objs #:nodoc:
44
+ raise ArgumentError, "nils aren't allowed into sorted array" \
45
+ if objs.include?(nil)
46
+ end
47
+
48
+ alias :old_insert :insert
49
+ private :old_insert
50
+ alias :old_sort! :sort!
51
+ private :old_sort!
52
+
53
+ def initialize *args, &b
54
+ @sort_block = proc { |a, b| a <=> b }
55
+
56
+ # Passed sort block.
57
+ if args.size == 0 && block_given?
58
+ @sort_block = b
59
+ super()
60
+ return
61
+ end
62
+
63
+ if args.size == 1
64
+ # Passed initial array.
65
+ if args.first.respond_to? :each
66
+ self.class._check_for_nil *args.first
67
+ super *args
68
+ old_sort!
69
+ return
70
+ end
71
+
72
+ # Passed size and block.
73
+ if block_given?
74
+ super *args, &b
75
+ self.class._check_for_nil *self
76
+ old_sort!
77
+ return
78
+ end
79
+
80
+ # Passed size, but not obj, which means fill with nils.
81
+ raise ArgumentError, "can't fill array with nils" \
82
+ if args.first.is_a? Numeric
83
+ end
84
+
85
+ super
86
+ end
87
+
88
+ # Not implemented methods.
89
+ #
90
+ # The following methods are not implemented mostly because they change order
91
+ # of elements. The rest ([]= and fill) arguably aren't useful on a sorted
92
+ # array.
93
+ def _not_implemented *args #:nodoc:
94
+ raise NotImplementedError
95
+ end
96
+
97
+ [:[]=, :fill, :insert, :reverse!, :rotate!, :shuffle!, :sort!, :unshift].
98
+ each { |m|
99
+ alias_method m, :_not_implemented
100
+ }
101
+
102
+ # Same as Array#collect!, but:
103
+ # * Disallow nils in the resulting array.
104
+ # * The resulting array is sorted.
105
+ def collect! &b
106
+ replace(collect &b)
107
+ end
108
+ alias :map! :collect!
109
+
110
+ # Same as Array#concat, but:
111
+ # * Disallow nils in the passed array.
112
+ # * The resulting array is sorted.
113
+ def concat other_ary
114
+ _add *other_ary
115
+ end
116
+
117
+ # Same as Array#flatten!, but:
118
+ # * Disallow nils in the resulting array.
119
+ # * The resulting array is sorted.
120
+ def flatten! *args
121
+ replace(flatten *args)
122
+ end
123
+
124
+ # Add objects to array, automatically placing them according to sort order.
125
+ # Disallow nils.
126
+ def push *objs
127
+ _add *objs
128
+ end
129
+ alias :<< :push
130
+
131
+ # Same as Array#replace, but:
132
+ # * Disallow nils in @other_ary.
133
+ # * The resulting array is sorted.
134
+ def replace other_ary
135
+ self.class._check_for_nil *other_ary
136
+ super
137
+ old_sort!
138
+ self
139
+ end
140
+
141
+ #private
142
+ # Name the following methods starting with underscore so as not to pollute
143
+ # Array namespace. They are considered private, but for testing purposes are
144
+ # left public.
145
+
146
+ def _add *objs #:nodoc:
147
+ self.class._check_for_nil *objs
148
+ objs.each { |obj|
149
+ old_insert _find_insert_position(obj), obj
150
+ }
151
+ self
152
+ end
153
+
154
+ def _check_can_calc_boundary? #:nodoc:
155
+ raise "can't calc boundary on empty array" if empty?
156
+ end
157
+
158
+ def _compare a, b #:nodoc:
159
+ ComparisonState.new(ret = @sort_block.call(a, b))
160
+ rescue ArgumentError
161
+ raise InvalidSortBlock,
162
+ "sort block returned invalid value: #{ret.inspect}"
163
+ end
164
+
165
+ def _find_insert_position element_to_place #:nodoc:
166
+ return 0 if empty?
167
+
168
+ start_idx, end_idx = 0, size - 1
169
+ loop {
170
+ middle_idx = _middle_element_index(start_idx, end_idx)
171
+ middle_el = self[middle_idx]
172
+ after_middle_idx = middle_idx + 1
173
+
174
+ comparison_state = _compare(element_to_place, middle_el)
175
+
176
+ # 1. Equals to the middle element. Insert after el.
177
+ return after_middle_idx if comparison_state.equal?
178
+
179
+ # 2. Less than the middle element.
180
+ if comparison_state.less?
181
+ # There's nothing to the left. So insert it as the first element.
182
+ return 0 if _left_boundary? middle_idx
183
+
184
+ end_idx = middle_idx - 1
185
+ next
186
+ end
187
+
188
+ # 3. Greater than the middle element.
189
+ #
190
+ # Right boundary? Put element_to_place after the last (middle) element.
191
+ return after_middle_idx if _right_boundary? middle_idx
192
+
193
+ # Less than after middle element? Put it right before it!
194
+ after_middle_el = self[after_middle_idx]
195
+ ret = _compare(element_to_place, after_middle_el)
196
+ return after_middle_idx if ret.equal? || ret.less?
197
+
198
+ # Proceeed to divide the right part.
199
+ start_idx = after_middle_idx
200
+ }
201
+ end
202
+
203
+ def _left_boundary? idx #:nodoc:
204
+ _check_can_calc_boundary?
205
+ idx == 0
206
+ end
207
+
208
+ def _middle_element_index start, ending #:nodoc:
209
+ start + (ending - start)/2
210
+ end
211
+
212
+ def _right_boundary? idx #:nodoc:
213
+ _check_can_calc_boundary?
214
+ idx == size - 1
215
+ end
216
+ end
@@ -0,0 +1,13 @@
1
+ require 'frugal_timeout'
2
+
3
+ MonotonicTime = FrugalTimeout::MonotonicTime
4
+
5
+ def say msg, sec
6
+ printf "%-24s %f\n", msg, sec
7
+ end
8
+
9
+ @ar = []
10
+ COUNT = 1000
11
+ COUNT.times {
12
+ @ar << rand(COUNT)
13
+ }
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require './common'
4
+ require '../lib/sorted_array_binary'
5
+
6
+ sec = MonotonicTime.measure { @ar.sort }
7
+ say 'sorting', sec
8
+
9
+ sec = MonotonicTime.measure {
10
+ sa = SortedArrayBinary.new
11
+ sa.push *@ar
12
+ }
13
+ say 'pushing into SortedArray', sec
14
+
15
+ sec = MonotonicTime.measure {
16
+ SortedArrayBinary.new @ar
17
+ }
18
+ say 'SortedArray.new', sec
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'frugal_timeout'
4
+ require 'sorted_array'
5
+ require 'array-sorted'
6
+ require './common'
7
+ require '../lib/sorted_array_binary'
8
+
9
+ def measure sorted_array_name, sorted_array_instance
10
+ sec = MonotonicTime.measure {
11
+ @ar.each { |el|
12
+ sorted_array_instance.push el
13
+ }
14
+ }
15
+ say sorted_array_name, sec
16
+ end
17
+
18
+ measure 'sorted_array',
19
+ SortedArray::SortedArray.new(SortedArray::DefaultSorter.new(:to_i))
20
+ measure 'array-sorted', Array::Sorted.new
21
+ measure 'sorted_array_binary', SortedArrayBinary.new
@@ -0,0 +1,16 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'sorted_array_binary'
3
+ s.version = '0.0.1'
4
+ s.date = '2014-01-29'
5
+ s.summary = 'Sorted array'
6
+ s.description = 'Sorted array using binary search'
7
+ s.authors = ['Dmitry Maksyoma']
8
+ s.email = 'ledestin@gmail.com'
9
+ s.files = `git ls-files`.split($\)
10
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
11
+ s.require_paths = ['lib']
12
+ s.homepage = 'https://github.com/ledestin/sorted_array_binary'
13
+
14
+ s.add_development_dependency 'rspec', '>= 2.13'
15
+ s.add_development_dependency 'hitimes', '~> 1.2'
16
+ end
@@ -0,0 +1,352 @@
1
+ require 'rspec'
2
+ require 'spec_helper'
3
+ require 'sorted_array_binary'
4
+
5
+ describe SortedArrayBinary do
6
+ before :each do
7
+ @ar = SortedArrayBinary.new
8
+ end
9
+
10
+ # {{{2 self._check_for_nil
11
+ context 'self._check_for_nil' do
12
+ it "raises exception if there's nil in passed objs" do
13
+ expect {
14
+ SortedArrayBinary._check_for_nil 'a', nil
15
+ }.to raise_error ArgumentError
16
+ end
17
+
18
+ it "doesn't raise exception if there's no nil in passed objs" do
19
+ expect {
20
+ SortedArrayBinary._check_for_nil 'a', 'b'
21
+ }.not_to raise_error
22
+ end
23
+ end
24
+
25
+ # {{{2 self.new
26
+ context 'self.new' do
27
+ it 'if passed size and obj, fills it' do
28
+ @ar = SortedArrayBinary.new 5, 'a'
29
+ @ar.should == ['a']*5
30
+ end
31
+
32
+ it 'if passed just size, raises exception' do
33
+ expect { SortedArrayBinary.new 5 }.to raise_error ArgumentError
34
+ end
35
+
36
+ it 'if passed single non-numeric argument, calls Array#new' do
37
+ expect { SortedArrayBinary.new 'a' }.to raise_error TypeError
38
+ end
39
+
40
+ context 'if passed array,' do
41
+ it 'sorts it' do
42
+ @ar = SortedArrayBinary.new ['b', 'a']
43
+ @ar.should == ['a', 'b']
44
+ end
45
+
46
+ it 'raises exception if nil found in passed array' do
47
+ expect { SortedArrayBinary.new [nil] }.to raise_error ArgumentError
48
+ end
49
+ end
50
+
51
+ it 'if passed size and block, fills it and sorts it' do
52
+ @ar = SortedArrayBinary.new(5) { |i| i == 0 ? 10 : i }
53
+ @ar.should == [1, 2, 3, 4, 10]
54
+ end
55
+
56
+ it 'if passed sorting block, resulting array is sorted using it' do
57
+ @ar = SortedArrayBinary.new { |a, b| b <=> a }
58
+ @ar.push 'a', 'b'
59
+ @ar.should == ['b', 'a']
60
+ end
61
+ end
62
+
63
+ # {{{2 Not implemented
64
+ context 'raises NotImplementedError exception when called' do
65
+ it '#[]=' do
66
+ expect { @ar[0] = 'a' }.to raise_error NotImplementedError
67
+ end
68
+
69
+ it '#fill' do
70
+ expect { @ar.fill nil }.to raise_error NotImplementedError
71
+ end
72
+
73
+ [:insert, :reverse!, :rotate!, :shuffle!, :sort!, :unshift].
74
+ each { |m|
75
+ it "##{m}" do
76
+ expect { @ar.send m }.to raise_error NotImplementedError
77
+ end
78
+ }
79
+ end
80
+
81
+ # {{{2 #collect!
82
+ [:collect!, :map!].each { |method|
83
+ context "##{method}" do
84
+ it 'after it, array is sorted' do
85
+ @ar.push 'a', 'b', 'c'
86
+ @ar.send(method) { |el|
87
+ case el
88
+ when 'a' then 9
89
+ when 'b' then 3
90
+ when 'c' then 1
91
+ end
92
+ }
93
+ @ar.should == [1, 3, 9]
94
+ end
95
+
96
+ it 'raises exception if one of resulting elements is nil' do
97
+ @ar.push 'a'
98
+ expect { @ar.send(method) { nil } }.to raise_error ArgumentError
99
+ @ar.should == ['a']
100
+ end
101
+ end
102
+ }
103
+
104
+ # {{{2 #concat
105
+ it '#concat adds another array and everything is sorted' do
106
+ @ar.push 'c'
107
+ @ar.concat ['a', 'b']
108
+ @ar.should == ['a', 'b', 'c']
109
+ end
110
+
111
+ # {{{2 #flatten!
112
+ context '#flatten!' do
113
+ it 'flattens array' do
114
+ @ar.push [1, 2], [4, 3]
115
+ @ar.flatten!
116
+ @ar.should == [1, 2, 3, 4]
117
+ end
118
+
119
+ it 'raises exception if resulting array contains nil' do
120
+ @ar.push [nil, 1]
121
+ expect { @ar.flatten! }.to raise_error ArgumentError
122
+ @ar.should == [[nil, 1]]
123
+ end
124
+ end
125
+
126
+ # {{{2 #push
127
+ [:<<, :push].each { |method|
128
+ context "##{method}" do
129
+ it 'adds an element to array' do
130
+ @ar.send method, 'a'
131
+ @ar.should == ['a']
132
+ end
133
+
134
+ it 'adds 2 elements to array' do
135
+ @ar.send method, 'a', 'b'
136
+ @ar.should == ['a', 'b']
137
+ end
138
+
139
+ it 'adds elements in random order, but the result is sorted' do
140
+ @ar.send method, 'b', 'a', 'd', 'c'
141
+ @ar.should == ['a', 'b', 'c', 'd']
142
+ @ar.send method, 'e'
143
+ @ar.should == ['a', 'b', 'c', 'd', 'e']
144
+ end
145
+
146
+ it 'adds element in random order, but sorting is done via sort block' do
147
+ @ar = SortedArrayBinary.new { |a, b| b <=> a }
148
+ @ar.push 'c', 'd'
149
+ @ar.push 'a', 'b'
150
+ @ar.should == ['d', 'c', 'b', 'a']
151
+ end
152
+
153
+ it 'raises exception if nil is passed' do
154
+ expect { @ar.send method, nil }.to raise_error ArgumentError
155
+ end
156
+ end
157
+ }
158
+
159
+ # {{{2 #replace
160
+ context '#replace' do
161
+ it '#replace replaces array, the resulting array is sorted' do
162
+ @ar.push 'a'
163
+ @ar.replace ['c', 'b']
164
+ @ar.should == ['b', 'c']
165
+ end
166
+
167
+ it "doesn't allow nils" do
168
+ expect { @ar.replace [nil] }.to raise_error ArgumentError
169
+ end
170
+ end
171
+
172
+ # {{{2 #_compare
173
+ context '#_compare' do
174
+ context 'sort block not given' do
175
+ it 'returns :equal if arguments are equal' do
176
+ @ar._compare(1, 1).equal?.should be_true
177
+ end
178
+
179
+ it 'returns :less if arg1 < arg2' do
180
+ @ar._compare(1, 2).less?.should be_true
181
+ end
182
+
183
+ it 'returns :greater if arg1 > arg2' do
184
+ @ar._compare(2, 1).greater?.should be_true
185
+ end
186
+ end
187
+
188
+ context 'sort block given' do
189
+ before :each do
190
+ @ar = SortedArrayBinary.new { |a, b| b <=> a }
191
+ end
192
+
193
+ it 'returns :equal if arguments are equal' do
194
+ @ar._compare(1, 1).equal?.should be_true
195
+ end
196
+
197
+ it 'returns :less if arg1 < arg2' do
198
+ @ar._compare(2, 1).less?.should be_true
199
+ end
200
+
201
+ it 'returns :greater if arg1 > arg2' do
202
+ @ar._compare(1, 2).greater?.should be_true
203
+ end
204
+
205
+ it 'raises exception if block returns value outside of -1, 0, 1' do
206
+ @ar = SortedArrayBinary.new { 'a' }
207
+ expect {
208
+ @ar.push 1, 2
209
+ }.to raise_error SortedArrayBinary::InvalidSortBlock
210
+ end
211
+ end
212
+ end
213
+
214
+ # {{{2 #_find_insert_position
215
+ context '#_find_insert_position' do
216
+ it 'returns 0 if array is empty' do
217
+ @ar._find_insert_position('a').should == 0
218
+ end
219
+
220
+ context 'and array contains single element,' do
221
+ it 'returns 1 if the first element is less than the passed elementt' do
222
+ @ar.push 'a'
223
+ @ar._find_insert_position('b').should == 1
224
+ end
225
+
226
+ it 'returns 0 if the first element is greater than the passed elementt' do
227
+ @ar.push 'b'
228
+ @ar._find_insert_position('a').should == 0
229
+ end
230
+
231
+ it 'returns 1 if the first element is equal to the passed elementt' do
232
+ @ar.push 'a'
233
+ @ar._find_insert_position('a').should == 1
234
+ end
235
+ end
236
+
237
+ context 'and array contains 2 elements,' do
238
+ it 'returns 2 if passed element is greater than 2nd element' do
239
+ @ar.push 'a', 'b'
240
+ @ar._find_insert_position('c').should == 2
241
+ end
242
+
243
+ it 'returns 1 if passed element is less than 2nd element' do
244
+ @ar.push 'a', 'c'
245
+ @ar._find_insert_position('b').should == 1
246
+ end
247
+
248
+ it 'returns 0 if passed element is less than 1st element' do
249
+ @ar.push 'b', 'c'
250
+ @ar._find_insert_position('a').should == 0
251
+ end
252
+ end
253
+
254
+ context 'and array context 4 elements,' do
255
+ it 'returns 1 if passed element is greater than 1st element' do
256
+ @ar.push 'a', 'c', 'd'
257
+ @ar._find_insert_position('b').should == 1
258
+ end
259
+ end
260
+ end
261
+
262
+ # {{{2 #_middle_element_index
263
+ context '_middle_element_index' do
264
+ it "returns first element index if there's one element" do
265
+ @ar._middle_element_index(0, 0).should == 0
266
+ @ar._middle_element_index(1, 1).should == 1
267
+ end
268
+
269
+ it 'returns 0 if there are 2 elements in the array' do
270
+ @ar._middle_element_index(0, 1).should == 0
271
+ end
272
+
273
+ it 'returns 1 if there are 3 elements in the array' do
274
+ @ar._middle_element_index(0, 2).should == 1
275
+ end
276
+
277
+ it 'returns 1 if there are 4 elements in the array' do
278
+ @ar._middle_element_index(0, 3).should == 1
279
+ end
280
+ end
281
+
282
+ # {{{2 #_left_boundary, #_right_boundary
283
+ context '#_left_boundary, #_right_boundary' do
284
+ context 'left' do
285
+ it "returns true if it's left boundary?" do
286
+ @ar.push 'a'
287
+ @ar._left_boundary?(0).should == true
288
+ end
289
+
290
+ it "returns false if it's not left boundary?" do
291
+ @ar.push 'a'
292
+ @ar._left_boundary?(1).should == false
293
+ end
294
+
295
+ it 'raises exception if array is empty' do
296
+ expect {
297
+ @ar._left_boundary?(0)
298
+ }.to raise_error
299
+ end
300
+ end
301
+
302
+ context 'right' do
303
+ it "returns true if it's right boundary?" do
304
+ @ar.push 'a', 'b'
305
+ @ar._right_boundary?(1).should == true
306
+ end
307
+
308
+ it "returns false if it's not right boundary?" do
309
+ @ar.push 'a', 'b'
310
+ @ar._right_boundary?(0).should == false
311
+ end
312
+
313
+ it 'raises exception if array is empty' do
314
+ expect {
315
+ @ar._right_boundary?(0)
316
+ }.to raise_error
317
+ end
318
+ end
319
+ end
320
+ # }}}2
321
+ end
322
+
323
+ describe SortedArrayBinary::ComparisonState do
324
+ [nil, -2, 2].each { |state|
325
+ it "allows only valid state in" do
326
+ expect {
327
+ SortedArrayBinary::ComparisonState.new state
328
+ }.to raise_error ArgumentError
329
+ end
330
+ }
331
+
332
+ it 'is equal? if state is 0' do
333
+ state = SortedArrayBinary::ComparisonState.new 0
334
+ state.equal?.should be_true
335
+ state.less?.should be_false
336
+ state.greater?.should be_false
337
+ end
338
+
339
+ it 'is greater? if state is 1' do
340
+ state = SortedArrayBinary::ComparisonState.new 1
341
+ state.greater?.should be_true
342
+ state.equal?.should be_false
343
+ state.less?.should be_false
344
+ end
345
+
346
+ it 'is less? if state is -1' do
347
+ state = SortedArrayBinary::ComparisonState.new -1
348
+ state.less?.should be_true
349
+ state.equal?.should be_false
350
+ state.greater?.should be_false
351
+ end
352
+ end
@@ -0,0 +1,2 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sorted_array_binary
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dmitry Maksyoma
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-01-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '2.13'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '2.13'
30
+ - !ruby/object:Gem::Dependency
31
+ name: hitimes
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.2'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.2'
46
+ description: Sorted array using binary search
47
+ email: ledestin@gmail.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - .coveralls.yml
53
+ - .gitignore
54
+ - .rspec
55
+ - .travis.yml
56
+ - Gemfile
57
+ - LICENSE
58
+ - README.md
59
+ - Rakefile
60
+ - lib/sorted_array_binary.rb
61
+ - perf-tests/common.rb
62
+ - perf-tests/perf-vs-sort
63
+ - perf-tests/perf-vs-sorted_array
64
+ - sorted_array_binary.gemspec
65
+ - spec/sorted_array_binary_spec.rb
66
+ - spec/spec_helper.rb
67
+ homepage: https://github.com/ledestin/sorted_array_binary
68
+ licenses: []
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 1.8.23
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Sorted array
91
+ test_files:
92
+ - spec/sorted_array_binary_spec.rb
93
+ - spec/spec_helper.rb
94
+ has_rdoc: