algorithms 0.6.1 → 1.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.
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