algorithms 0.6.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d542bb52d6a148cc95802bfc5d84549e605b7077009343496e51a00d405bed05
4
+ data.tar.gz: b66ba40d7c3b4d29f108294e2623f85c48f52f1cdcfa7282191ed412d1877cf5
5
+ SHA512:
6
+ metadata.gz: 3bacbfc0793cce5bb67c51b33a64a6a4bb91e0d2cdfea661e5ee5721433bdbc19b723724ebb54e86289b053e71740dcd4c70a7e02fbed998015cd4fa31728f67
7
+ data.tar.gz: f2ec4934f51e631750aea36af36fb33a4b2dc0fee95ec1b138a8e97c75952b341f9f235e17a12868bb9233e88f6bb4bcfff0800e47fefe417712ee9167d389b1
data/README.markdown CHANGED
@@ -1,4 +1,6 @@
1
- # algorithms [![Build Status](https://travis-ci.org/kanwei/algorithms.png)](https://travis-ci.org/kanwei/algorithms)
1
+ # algorithms [![Build Status](https://travis-ci.org/kanwei/algorithms.svg?branch=master)](https://travis-ci.org/github/kanwei/algorithms)
2
+
3
+ [API Documentation](http://kanwei.github.io/algorithms/)
2
4
 
3
5
  ## DESCRIPTION:
4
6
 
@@ -6,7 +8,7 @@ Started as a [Google Summer of Code 2008](http://code.google.com/soc/2008/ruby/a
6
8
 
7
9
  Written by [Kanwei Li](http://kanwei.com/), mentored by Austin Ziegler
8
10
 
9
- ### Original Proposal: ###
11
+ ## Original Proposal: ##
10
12
 
11
13
  Using the right data structure or algorithm for the situation is an important
12
14
  aspect of programming. In computer science literature, many data structures
@@ -41,6 +43,7 @@ compare performance in different situations.
41
43
  - Shell sort Algorithms::Sort.shell_sort
42
44
  - Quicksort Algorithms::Sort.quicksort
43
45
  - Mergesort Algorithms::Sort.mergesort
46
+ - Dual-Pivot Quicksort Algorithms::Sort.dualpivotquicksort
44
47
 
45
48
  ## SYNOPSIS:
46
49
 
@@ -60,25 +63,4 @@ compare performance in different situations.
60
63
 
61
64
  ## LICENSE:
62
65
 
63
- (The MIT License)
64
-
65
- Ruby Algorithms and Containers project is Copyright (c) 2009 Kanwei Li
66
-
67
- Permission is hereby granted, free of charge, to any person obtaining
68
- a copy of this software and associated documentation files (the
69
- 'Software'), to deal in the Software without restriction, including
70
- without limitation the rights to use, copy, modify, merge, publish,
71
- distribute, sublicense, and/or sell copies of the Software, and to
72
- permit persons to whom the Software is furnished to do so, subject to
73
- the following conditions:
74
-
75
- The above copyright notice and this permission notice shall be
76
- included in all copies or substantial portions of the Software.
77
-
78
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
79
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
80
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
81
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
82
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
83
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
84
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
66
+ See [LICENSE.md](LICENSE.md).
data/Rakefile CHANGED
@@ -16,3 +16,7 @@ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
16
16
  else
17
17
  task :default => [:compile, :spec]
18
18
  end
19
+
20
+ task :rdoc do
21
+ `rdoc -f hanna --main algorithms.rb -t "Ruby Algorithms and Containers Documentation"`
22
+ end
data/algorithms.gemspec CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "algorithms"
5
- s.version = "0.6.1"
5
+ s.version = "1.0.1"
6
6
 
7
7
  s.authors = ["Kanwei Li"]
8
8
  s.email = "kanwei@gmail.com"
9
9
  s.license = 'MIT'
10
- s.date = "2013-01-22"
10
+ s.date = "2023-11-11"
11
11
  s.summary = "Useful algorithms and data structures for Ruby. Optional C extensions."
12
12
  s.description = "Heap, Priority Queue, Deque, Stack, Queue, Red-Black Trees, Splay Trees, sorting algorithms, and more"
13
13
  if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
@@ -19,5 +19,4 @@ Gem::Specification.new do |s|
19
19
  s.homepage = "https://github.com/kanwei/algorithms"
20
20
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Algorithms", "--main", "README.markdown"]
21
21
  s.require_paths = ["lib", "ext"]
22
- s.rubyforge_project = "algorithms"
23
22
  end
@@ -26,7 +26,7 @@ long levenshtein_distance(VALUE str1, VALUE str2) {
26
26
  s1_len++;
27
27
  s2_len++;
28
28
 
29
- d = malloc(sizeof(typeof(d)) * (s1_len) * (s2_len));
29
+ d = xmalloc(sizeof(typeof(d)) * s1_len * s2_len);
30
30
 
31
31
  for (i = 0; i < s1_len; i++) {
32
32
  d[i] = i; // d[i, 0] = i
@@ -49,7 +49,7 @@ long levenshtein_distance(VALUE str1, VALUE str2) {
49
49
  }
50
50
  }
51
51
  i = d[s1_len * s2_len -1];
52
- free(d);
52
+ xfree(d);
53
53
  return i;
54
54
  }
55
55
 
@@ -172,7 +172,7 @@ static void recursively_free_nodes(bst_node *node) {
172
172
  if(node) {
173
173
  recursively_free_nodes(node->left);
174
174
  recursively_free_nodes(node->right);
175
- free(node);
175
+ xfree(node);
176
176
  }
177
177
  }
178
178
 
@@ -19,7 +19,7 @@ void free_nodes(deque_node *node) {
19
19
  deque_node *next;
20
20
  while(node) {
21
21
  next = node->right;
22
- free(node);
22
+ xfree(node);
23
23
  node = next;
24
24
  }
25
25
  return;
@@ -71,7 +71,7 @@ static void deque_free(void *ptr) {
71
71
  if (ptr) {
72
72
  deque *deque = ptr;
73
73
  free_nodes(deque->front);
74
- free(deque);
74
+ xfree(deque);
75
75
  }
76
76
  }
77
77
 
@@ -31,7 +31,7 @@ static void recursively_free_nodes(rbtree_node *node) {
31
31
  if(node) {
32
32
  recursively_free_nodes(node->left);
33
33
  recursively_free_nodes(node->right);
34
- free(node);
34
+ xfree(node);
35
35
  }
36
36
  return;
37
37
  }
@@ -198,7 +198,7 @@ static rbtree_node* delete_min(rbtree_node *h, VALUE *deleted_value) {
198
198
  if ( !h->left ) {
199
199
  if(deleted_value)
200
200
  *deleted_value = h->value;
201
- free(h);
201
+ xfree(h);
202
202
  return NULL;
203
203
  }
204
204
 
@@ -216,7 +216,7 @@ static rbtree_node* delete_max(rbtree_node *h, VALUE *deleted_value) {
216
216
 
217
217
  if ( !h->right ) {
218
218
  *deleted_value = h->value;
219
- free(h);
219
+ xfree(h);
220
220
  return NULL;
221
221
  }
222
222
 
@@ -245,7 +245,7 @@ static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *de
245
245
  cmp = tree->compare_function(key, node->key);
246
246
  if ( (cmp == 0) && !node->right ) {
247
247
  *deleted_value = node->value;
248
- free(node);
248
+ xfree(node);
249
249
  return NULL;
250
250
  }
251
251
 
@@ -339,7 +339,7 @@ static void rbtree_mark(void *ptr) {
339
339
  }
340
340
  old = current;
341
341
  current = current->next;
342
- free(old);
342
+ xfree(old);
343
343
  }
344
344
  }
345
345
  }
@@ -349,7 +349,7 @@ static void rbtree_free(void *ptr) {
349
349
  if (ptr) {
350
350
  rbtree *tree = ptr;
351
351
  recursively_free_nodes(tree->root);
352
- free(tree);
352
+ xfree(tree);
353
353
  }
354
354
  }
355
355
 
@@ -28,7 +28,7 @@ static void recursively_free_nodes(splaytree_node *node) {
28
28
  if(node) {
29
29
  recursively_free_nodes(node->left);
30
30
  recursively_free_nodes(node->right);
31
- free(node);
31
+ xfree(node);
32
32
  }
33
33
  return;
34
34
  }
@@ -199,7 +199,7 @@ static splaytree_node* delete(splaytree *tree, splaytree_node *n, VALUE key, VAL
199
199
  x = splay(tree, n->left, key);
200
200
  x->right = n->right;
201
201
  }
202
- free(n);
202
+ xfree(n);
203
203
  if (x) {
204
204
  x->size = tsize-1;
205
205
  }
@@ -282,7 +282,7 @@ static void splaytree_mark(void *ptr) {
282
282
  }
283
283
  old = current;
284
284
  current = current->next;
285
- free(old);
285
+ xfree(old);
286
286
  }
287
287
  }
288
288
  }
@@ -292,7 +292,7 @@ static void splaytree_free(void *ptr) {
292
292
  if (ptr) {
293
293
  splaytree *tree = ptr;
294
294
  recursively_free_nodes(tree->root);
295
- free(tree);
295
+ xfree(tree);
296
296
  }
297
297
  }
298
298
 
@@ -235,4 +235,134 @@ module Algorithms::Sort
235
235
  sorted + left + right
236
236
  end
237
237
 
238
+ # Dual-Pivot Quicksort is a variation of Quicksort by Vladimir Yaroslavskiy.
239
+ # This is an implementation of the algorithm as it was found in the original
240
+ # research paper:
241
+ #
242
+ # http://iaroslavski.narod.ru/quicksort/DualPivotQuicksort.pdf
243
+ #
244
+ # Mirror:
245
+ # http://codeblab.com/wp-content/uploads/2009/09/DualPivotQuicksort.pdf
246
+ #
247
+ # "This algorithm offers O(n log(n)) performance on many data sets that cause
248
+ # other quicksorts to degrade to quadratic performance, and is typically
249
+ # faster than traditional (one-pivot) Quicksort implementations."
250
+ # -- http://download.oracle.com/javase/7/docs/api/java/util/Arrays.html
251
+ #
252
+ # The algorithm was improved by Vladimir Yaroslavskiy, Jon Bentley, and
253
+ # Joshua Bloch, and was implemented as the default sort algorithm for
254
+ # primatives in Java 7.
255
+ #
256
+ # Implementation in the Java JDK as of November, 2011:
257
+ # http://www.docjar.com/html/api/java/util/DualPivotQuicksort.java.html
258
+ #
259
+ # It is proved that for the Dual-Pivot Quicksort the average number
260
+ # of comparisons is 2*n*ln(n), the average number of swaps is
261
+ # 0.8*n*ln(n), whereas classical Quicksort algorithm has 2*n*ln(n)
262
+ # and 1*n*ln(n) respectively. This has been fully examined mathematically
263
+ # and experimentally.
264
+ #
265
+ # Requirements: Container should implement #pop and include the Enumerable module.
266
+ # Time Complexity: О(n log n) average, О(n log n) worst-case
267
+ # Space Complexity: О(n) auxiliary
268
+ #
269
+ # Stable: No
270
+ #
271
+ # Algorithms::Sort.dualpivotquicksort [5, 4, 3, 1, 2] => [1, 2, 3, 4, 5]
272
+
273
+ def self.dualpivotquicksort(container)
274
+ return container if container.size <= 1
275
+ dualpivot(container, 0, container.size-1, 3)
276
+ end
277
+
278
+ def self.dualpivot(container, left=0, right=container.size-1, div=3)
279
+ length = right - left
280
+ if length < 27 # insertion sort for tiny array
281
+ container.each_with_index do |data,i|
282
+ j = i - 1
283
+ while j >= 0
284
+ break if container[j] <= data
285
+ container[j + 1] = container[j]
286
+ j = j - 1
287
+ end
288
+ container[j + 1] = data
289
+ end
290
+ else # full dual-pivot quicksort
291
+ third = length / div
292
+ # medians
293
+ m1 = left + third
294
+ m2 = right - third
295
+ if m1 <= left
296
+ m1 = left + 1
297
+ end
298
+ if m2 >= right
299
+ m2 = right - 1
300
+ end
301
+ if container[m1] < container[m2]
302
+ dualpivot_swap(container, m1, left)
303
+ dualpivot_swap(container, m2, right)
304
+ else
305
+ dualpivot_swap(container, m1, right)
306
+ dualpivot_swap(container, m2, left)
307
+ end
308
+ # pivots
309
+ pivot1 = container[left]
310
+ pivot2 = container[right]
311
+ # pointers
312
+ less = left + 1
313
+ great = right - 1
314
+ # sorting
315
+ k = less
316
+ while k <= great
317
+ if container[k] < pivot1
318
+ dualpivot_swap(container, k, less += 1)
319
+ elsif container[k] > pivot2
320
+ while k < great && container[great] > pivot2
321
+ great -= 1
322
+ end
323
+ dualpivot_swap(container, k, great -= 1)
324
+ if container[k] < pivot1
325
+ dualpivot_swap(container, k, less += 1)
326
+ end
327
+ end
328
+ k += 1
329
+ end
330
+ # swaps
331
+ dist = great - less
332
+ if dist < 13
333
+ div += 1
334
+ end
335
+ dualpivot_swap(container, less-1, left)
336
+ dualpivot_swap(container, great+1, right)
337
+ # subarrays
338
+ dualpivot(container, left, less-2, div)
339
+ dualpivot(container, great+2, right, div)
340
+ # equal elements
341
+ if dist > length - 13 && pivot1 != pivot2
342
+ for k in less..great do
343
+ if container[k] == pivot1
344
+ dualpivot_swap(container, k, less)
345
+ less += 1
346
+ elsif container[k] == pivot2
347
+ dualpivot_swap(container, k, great)
348
+ great -= 1
349
+ if container[k] == pivot1
350
+ dualpivot_swap(container, k, less)
351
+ less += 1
352
+ end
353
+ end
354
+ end
355
+ end
356
+ # subarray
357
+ if pivot1 < pivot2
358
+ dualpivot(container, less, great, div)
359
+ end
360
+ container
361
+ end
362
+ end
363
+
364
+ def self.dualpivot_swap(container, i, j)
365
+ container[i], container[j] = container[j], container[i]
366
+ end
238
367
  end
368
+
data/lib/algorithms.rb CHANGED
@@ -43,6 +43,7 @@
43
43
  - Shell sort - Algorithms::Sort.shell_sort
44
44
  - Quicksort - Algorithms::Sort.quicksort
45
45
  - Mergesort - Algorithms::Sort.mergesort
46
+ - Dual-Pivot Quicksort - Algorithms::Sort.dualpivotquicksort
46
47
  * String algorithms
47
48
  - Levenshtein distance - Algorithms::String.levenshtein_dist
48
49
  =end
@@ -75,13 +75,6 @@ class Containers::Heap
75
75
  end
76
76
  @size += 1
77
77
 
78
- arr = []
79
- w = @next.right
80
- until w == @next do
81
- arr << w.value
82
- w = w.right
83
- end
84
- arr << @next.value
85
78
  @stored[key] ||= []
86
79
  @stored[key] << node
87
80
  value
@@ -15,7 +15,7 @@ require 'containers/stack'
15
15
  explicitly used as well; their functionality is identical.
16
16
 
17
17
  Most methods have O(log n) complexity.
18
-
18
+
19
19
  =end
20
20
  class Containers::RubyRBTreeMap
21
21
  include Enumerable
@@ -160,7 +160,7 @@ class Containers::RubyRBTreeMap
160
160
  result
161
161
  end
162
162
 
163
- # Deletes the item with the smallest key and returns the item. Returns nil
163
+ # Deletes the item with the largest key and returns the item. Returns nil
164
164
  # if key is not present.
165
165
  #
166
166
  # Complexity: O(log n)
@@ -12,10 +12,10 @@ class Containers::SuffixArray
12
12
  #
13
13
  # Complexity: O(n^2 log n)
14
14
  #
15
- # s_array = Containers::SuffixArray("abracadabra")
15
+ # s_array = Containers::SuffixArray.new("abracadabra")
16
16
  # s_array["abra"] #=> true
17
17
  #
18
- # number = Containers::SuffixArray(1234567)
18
+ # number = Containers::SuffixArray.new(1234567)
19
19
  # number[1] #=> true
20
20
  # number[13] #=> false
21
21
  def initialize(string)
@@ -65,4 +65,4 @@ class Containers::SuffixArray
65
65
  return false
66
66
  end
67
67
  alias_method :[], :has_substring?
68
- end
68
+ end
@@ -12,7 +12,7 @@ if defined? Containers::CDeque
12
12
  # Check if any instances were swept
13
13
  count = 0
14
14
  ObjectSpace.each_object(anon_class) { |x| count += 1 }
15
- count.should eql(100)
15
+ expect(count).to eql(100)
16
16
  end
17
17
  end
18
18
  end
data/spec/deque_spec.rb CHANGED
@@ -3,31 +3,31 @@ require 'algorithms'
3
3
 
4
4
  shared_examples "(empty deque)" do
5
5
  it "should return nil when popping objects" do
6
- @deque.pop_front.should be_nil
7
- @deque.pop_back.should be_nil
6
+ expect(@deque.pop_front).to be_nil
7
+ expect(@deque.pop_back).to be_nil
8
8
  end
9
9
 
10
10
  it "should return a size of 1 when sent #push_front" do
11
11
  @deque.push_front(1)
12
- @deque.size.should eql(1)
12
+ expect(@deque.size).to eql(1)
13
13
  end
14
14
 
15
15
  it "should return a size of 1 when sent #push_back" do
16
16
  @deque.push_back(1)
17
- @deque.size.should eql(1)
17
+ expect(@deque.size).to eql(1)
18
18
  end
19
19
 
20
20
  it "should return nil when sent #front and #back" do
21
- @deque.front.should be_nil
22
- @deque.back.should be_nil
21
+ expect(@deque.front).to be_nil
22
+ expect(@deque.back).to be_nil
23
23
  end
24
24
 
25
25
  it "should be empty" do
26
- @deque.should be_empty
26
+ expect(@deque).to be_empty
27
27
  end
28
28
 
29
29
  it "should raise ArgumentError if passed more than one argument" do
30
- lambda { @deque.class.send("new", Time.now, []) }.should raise_error
30
+ expect { @deque.class.send("new", Time.now, []) }.to raise_error(ArgumentError)
31
31
  end
32
32
  end
33
33
 
@@ -38,40 +38,40 @@ shared_examples "(non-empty deque)" do
38
38
  end
39
39
 
40
40
  it "should return last pushed object with pop_back" do
41
- @deque.pop_back.should eql("10")
42
- @deque.pop_back.should eql(10)
41
+ expect(@deque.pop_back).to eql("10")
42
+ expect(@deque.pop_back).to eql(10)
43
43
  end
44
44
 
45
45
  it "should return first pushed object with pop_front" do
46
- @deque.pop_front.should eql(10)
47
- @deque.pop_front.should eql("10")
46
+ expect(@deque.pop_front).to eql(10)
47
+ expect(@deque.pop_front).to eql("10")
48
48
  end
49
49
 
50
50
  it "should return a size greater than 0" do
51
- @deque.size.should eql(2)
51
+ expect(@deque.size).to eql(2)
52
52
  end
53
53
 
54
54
  it "should not be empty" do
55
- @deque.should_not be_empty
55
+ expect(@deque).not_to be_empty
56
56
  end
57
57
 
58
58
  it "should iterate in LIFO order with #each_backward" do
59
59
  arr = []
60
60
  @deque.each_backward { |obj| arr << obj }
61
- arr.should eql(["10", 10])
61
+ expect(arr).to eql(["10", 10])
62
62
  end
63
63
 
64
64
  it "should iterate in FIFO order with #each_forward" do
65
65
  arr = []
66
66
  @deque.each_forward { |obj| arr << obj }
67
- arr.should eql([10, "10"])
67
+ expect(arr).to eql([10, "10"])
68
68
  end
69
69
 
70
70
  it "should return nil after everything's popped" do
71
71
  @deque.pop_back
72
72
  @deque.pop_back
73
- @deque.pop_back.should be_nil
74
- @deque.front.should be_nil
73
+ expect(@deque.pop_back).to be_nil
74
+ expect(@deque.front).to be_nil
75
75
  end
76
76
  end
77
77
 
data/spec/heap_spec.rb CHANGED
@@ -7,29 +7,29 @@ describe Containers::Heap do
7
7
  end
8
8
 
9
9
  it "should not let you merge with non-heaps" do
10
- lambda { @heap.merge!(nil) }.should raise_error
11
- lambda { @heap.merge!([]) }.should raise_error
10
+ expect { @heap.merge!(nil) }.to raise_error(ArgumentError)
11
+ expect { @heap.merge!([]) }.to raise_error(ArgumentError)
12
12
  end
13
13
 
14
14
  describe "(empty)" do
15
15
 
16
16
  it "should return nil when getting the maximum" do
17
- @heap.max!.should be_nil
17
+ expect(@heap.max!).to be_nil
18
18
  end
19
19
 
20
20
  it "should let you insert and remove one item" do
21
- @heap.size.should eql(0)
21
+ expect(@heap.size).to eql(0)
22
22
 
23
23
  @heap.push(1)
24
- @heap.size.should eql(1)
24
+ expect(@heap.size).to eql(1)
25
25
 
26
- @heap.max!.should eql(1)
27
- @heap.size.should eql(0)
26
+ expect(@heap.max!).to eql(1)
27
+ expect(@heap.size).to eql(0)
28
28
  end
29
29
 
30
30
  it "should let you initialize with an array" do
31
31
  @heap = Containers::MaxHeap.new([1,2,3])
32
- @heap.size.should eql(3)
32
+ expect(@heap.size).to eql(3)
33
33
  end
34
34
 
35
35
  end
@@ -38,25 +38,25 @@ describe Containers::Heap do
38
38
  before(:each) do
39
39
  @random_array = []
40
40
  @num_items = 100
41
- @num_items.times { |x| @random_array << rand(@num_items) }
41
+ @num_items.times { @random_array << rand(@num_items) }
42
42
  @heap = Containers::MaxHeap.new(@random_array)
43
43
  end
44
44
 
45
45
  it "should display the correct size" do
46
- @heap.size.should eql(@num_items)
46
+ expect(@heap.size).to eql(@num_items)
47
47
  end
48
48
 
49
49
  it "should have a next value" do
50
- @heap.next.should be_true
51
- @heap.next_key.should be_true
50
+ expect(@heap.next).to be_truthy
51
+ expect(@heap.next_key).to be_truthy
52
52
  end
53
53
 
54
54
  it "should delete random keys" do
55
- @heap.delete(@random_array[0]).should eql(@random_array[0])
56
- @heap.delete(@random_array[1]).should eql(@random_array[1])
55
+ expect(@heap.delete(@random_array[0])).to eql(@random_array[0])
56
+ expect(@heap.delete(@random_array[1])).to eql(@random_array[1])
57
57
  ordered = []
58
58
  ordered << @heap.max! until @heap.empty?
59
- ordered.should eql( @random_array[2..-1].sort.reverse )
59
+ expect(ordered).to eql( @random_array[2..-1].sort.reverse )
60
60
  end
61
61
 
62
62
  it "should delete all keys" do
@@ -64,15 +64,15 @@ describe Containers::Heap do
64
64
  @random_array.size.times do |t|
65
65
  ordered << @heap.delete(@random_array[t])
66
66
  end
67
- @heap.should be_empty
68
- ordered.should eql( @random_array )
67
+ expect(@heap).to be_empty
68
+ expect(ordered).to eql( @random_array )
69
69
  end
70
70
 
71
71
  it "should be in max->min order" do
72
72
  ordered = []
73
73
  ordered << @heap.max! until @heap.empty?
74
74
 
75
- ordered.should eql(@random_array.sort.reverse)
75
+ expect(ordered).to eql(@random_array.sort.reverse)
76
76
  end
77
77
 
78
78
  it "should change certain keys" do
@@ -84,12 +84,12 @@ describe Containers::Heap do
84
84
  heap.change_key(8, 0)
85
85
  ordered = []
86
86
  ordered << heap.min! until heap.empty?
87
- ordered.should eql( [8,3,4,5,6,7,9,10,101,100] )
87
+ expect(ordered).to eql( [8,3,4,5,6,7,9,10,101,100] )
88
88
  end
89
89
 
90
90
  it "should not delete keys it doesn't have" do
91
- @heap.delete(:nonexisting).should be_nil
92
- @heap.size.should eql(@num_items)
91
+ expect(@heap.delete(:nonexisting)).to be_nil
92
+ expect(@heap.size).to eql(@num_items)
93
93
  end
94
94
 
95
95
  it "should delete certain keys" do
@@ -101,19 +101,19 @@ describe Containers::Heap do
101
101
  heap.delete(100)
102
102
  ordered = []
103
103
  ordered << heap.min! until heap.empty?
104
- ordered.should eql( [3,4,6,7,8,9,10,101] )
104
+ expect(ordered).to eql( [3,4,6,7,8,9,10,101] )
105
105
  end
106
106
 
107
107
  it "should let you merge with another heap" do
108
108
  numbers = [1,2,3,4,5,6,7,8]
109
109
  otherheap = Containers::MaxHeap.new(numbers)
110
- otherheap.size.should eql(8)
110
+ expect(otherheap.size).to eql(8)
111
111
  @heap.merge!(otherheap)
112
112
 
113
113
  ordered = []
114
114
  ordered << @heap.max! until @heap.empty?
115
115
 
116
- ordered.should eql( (@random_array + numbers).sort.reverse)
116
+ expect(ordered).to eql( (@random_array + numbers).sort.reverse)
117
117
  end
118
118
 
119
119
  describe "min-heap" do
@@ -122,7 +122,7 @@ describe Containers::Heap do
122
122
  ordered = []
123
123
  ordered << @heap.min! until @heap.empty?
124
124
 
125
- ordered.should eql(@random_array.sort)
125
+ expect(ordered).to eql(@random_array.sort)
126
126
  end
127
127
  end
128
128
 
data/spec/kd_tree_spec.rb CHANGED
@@ -6,7 +6,7 @@ describe Containers::KDTree do
6
6
  kdtree = Containers::KDTree.new( {0 => [4, 3], 1 => [3, 0], 2 => [-1, 2], 3 => [6, 4],
7
7
  4 => [3, -5], 5 => [-2, -5] })
8
8
  closest_2 = kdtree.find_nearest([0, 0], 2)
9
- closest_2.should eql([[5, 2], [9, 1]])
9
+ expect(closest_2).to eql([[5, 2], [9, 1]])
10
10
  end
11
11
 
12
12
  it "should work for real-life example from facebook puzzle" do
@@ -28,7 +28,7 @@ describe Containers::KDTree do
28
28
  }
29
29
 
30
30
  expected = File.read(File.join(File.dirname(__FILE__), 'kd_expected_out.txt'))
31
- expected.should eql(out)
31
+ expect(expected).to eql(out)
32
32
  end
33
33
 
34
34
  end