algorithms 0.0.1 → 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.
Files changed (54) hide show
  1. data/History.txt +139 -2
  2. data/Manifest +31 -8
  3. data/README +90 -0
  4. data/Rakefile +22 -9
  5. data/algorithms.gemspec +28 -101
  6. data/benchmark.rb +29 -27
  7. data/benchmarks/rbench.rb +16 -0
  8. data/benchmarks/rbench/column.rb +26 -0
  9. data/benchmarks/rbench/group.rb +43 -0
  10. data/benchmarks/rbench/report.rb +53 -0
  11. data/benchmarks/rbench/runner.rb +109 -0
  12. data/benchmarks/rbench/summary.rb +51 -0
  13. data/benchmarks/sorts.rb +33 -0
  14. data/ext/containers/bst/bst.c +205 -0
  15. data/ext/containers/{priority_queue → bst}/extconf.rb +1 -1
  16. data/ext/containers/deque/deque.c +233 -0
  17. data/ext/containers/deque/extconf.rb +4 -0
  18. data/ext/containers/tree_map/extconf.rb +1 -1
  19. data/ext/containers/tree_map/rbtree.c +73 -25
  20. data/lib/algorithms.rb +65 -6
  21. data/lib/algorithms/search.rb +84 -0
  22. data/lib/algorithms/sort.rb +238 -0
  23. data/lib/containers/deque.rb +176 -0
  24. data/lib/containers/heap.rb +451 -111
  25. data/lib/containers/kd_tree.rb +87 -0
  26. data/lib/containers/priority_queue.rb +107 -508
  27. data/lib/containers/queue.rb +62 -23
  28. data/lib/containers/rb_tree_map.rb +398 -0
  29. data/lib/containers/splay_tree_map.rb +274 -0
  30. data/lib/containers/stack.rb +59 -21
  31. data/lib/containers/suffix_array.rb +68 -0
  32. data/lib/containers/trie.rb +182 -0
  33. data/lib/graphs/graph.rb +25 -0
  34. data/spec/bst_spec.rb +31 -0
  35. data/spec/deque_spec.rb +108 -0
  36. data/spec/heap_spec.rb +111 -66
  37. data/spec/kd_tree_spec.rb +89 -0
  38. data/spec/priority_queue_spec.rb +71 -27
  39. data/spec/queue_spec.rb +53 -45
  40. data/spec/rb_tree_map_spec.rb +123 -0
  41. data/spec/search_spec.rb +28 -0
  42. data/spec/sort_spec.rb +28 -0
  43. data/spec/splay_tree_map_spec.rb +102 -0
  44. data/spec/stack_spec.rb +56 -49
  45. data/spec/suffix_array_spec.rb +40 -0
  46. data/spec/trie_spec.rb +59 -0
  47. metadata +54 -32
  48. data/README.txt +0 -58
  49. data/ext/containers/priority_queue/priority_queue.c +0 -948
  50. data/ext/containers/tree_map/Rakefile +0 -4
  51. data/lib/containers/hash.rb +0 -0
  52. data/lib/containers/tree_map.rb +0 -265
  53. data/spec/priority_queue_test.rb +0 -371
  54. data/spec/tree_map_spec.rb +0 -99
@@ -1,4 +1,4 @@
1
1
  require 'mkmf'
2
- extension_name = "CPriorityQueue"
2
+ extension_name = "CBst"
3
3
  dir_config(extension_name)
4
4
  create_makefile(extension_name)
@@ -0,0 +1,233 @@
1
+ #include "ruby.h"
2
+
3
+ #define FALSE 0
4
+ #define TRUE 1
5
+
6
+ typedef struct struct_deque_node {
7
+ VALUE obj;
8
+ struct struct_deque_node *left;
9
+ struct struct_deque_node *right;
10
+ } deque_node;
11
+
12
+ typedef struct {
13
+ unsigned int size;
14
+ deque_node *front;
15
+ deque_node *back;
16
+ } deque;
17
+
18
+ void free_nodes(deque_node *node) {
19
+ deque_node *next;
20
+ while(node) {
21
+ next = node->right;
22
+ free(node);
23
+ node = next;
24
+ }
25
+ return;
26
+ }
27
+
28
+ void clear_deque(deque *a_deque) {
29
+ if(a_deque->front)
30
+ free_nodes(a_deque->front);
31
+ a_deque->size = 0;
32
+ a_deque->front = NULL;
33
+ a_deque->back = NULL;
34
+ return;
35
+ }
36
+
37
+ static deque* get_deque_from_self(VALUE self) {
38
+ deque *a_deque;
39
+ Data_Get_Struct(self, deque, a_deque);
40
+ return a_deque;
41
+ }
42
+
43
+ static deque* create_deque() {
44
+ deque *a_deque = ALLOC(deque);
45
+ a_deque->size = 0;
46
+ a_deque->front = NULL;
47
+ a_deque->back = NULL;
48
+ return a_deque;
49
+ }
50
+
51
+ static deque_node* create_node(VALUE obj) {
52
+ deque_node *node = ALLOC(deque_node);
53
+ node->obj = obj;
54
+ node->left = NULL;
55
+ node->right = NULL;
56
+ return node;
57
+ }
58
+
59
+ static void deque_free(deque *deque) {
60
+ free_nodes(deque->front);
61
+ free(deque);
62
+ }
63
+
64
+ static VALUE deque_alloc(VALUE klass) {
65
+ deque *deque = create_deque();
66
+ return Data_Wrap_Struct(klass, NULL, deque_free, deque);
67
+ }
68
+
69
+ static VALUE deque_push_front(VALUE self, VALUE obj) {
70
+ deque *deque = get_deque_from_self(self);
71
+ deque_node *node = create_node(obj);
72
+ if(deque->front) {
73
+ node->right = deque->front;
74
+ deque->front->left = node;
75
+ deque->front = node;
76
+ }
77
+ else {
78
+ deque->front = node;
79
+ deque->back = node;
80
+ }
81
+ deque->size++;
82
+ return obj;
83
+ }
84
+
85
+ static VALUE deque_push_back(VALUE self, VALUE obj) {
86
+ deque *deque = get_deque_from_self(self);
87
+ deque_node *node = create_node(obj);
88
+ if(deque->back) {
89
+ node->left = deque->back;
90
+ deque->back->right = node;
91
+ deque->back = node;
92
+ }
93
+ else {
94
+ deque->front = node;
95
+ deque->back = node;
96
+ }
97
+ deque->size++;
98
+ return obj;
99
+ }
100
+
101
+ static VALUE deque_pop_front(VALUE self) {
102
+ deque *deque = get_deque_from_self(self);
103
+ VALUE obj;
104
+ if(!deque->front)
105
+ return Qnil;
106
+ deque_node *node = deque->front;
107
+ obj = node->obj;
108
+ if(deque->size == 1) {
109
+ clear_deque(deque);
110
+ return obj;
111
+ }
112
+ deque->front->right->left = NULL;
113
+ deque->front = deque->front->right;
114
+ deque->size--;
115
+ return obj;
116
+ }
117
+
118
+ static VALUE deque_front(VALUE self) {
119
+ deque *deque = get_deque_from_self(self);
120
+ if(deque->front)
121
+ return deque->front->obj;
122
+
123
+ return Qnil;
124
+ }
125
+
126
+ static VALUE deque_back(VALUE self) {
127
+ deque *deque = get_deque_from_self(self);
128
+ if(deque->back)
129
+ return deque->back->obj;
130
+
131
+ return Qnil;
132
+ }
133
+
134
+ static VALUE deque_pop_back(VALUE self) {
135
+ deque *deque = get_deque_from_self(self);
136
+ VALUE obj;
137
+ if(!deque->back)
138
+ return Qnil;
139
+ deque_node *node = deque->back;
140
+ obj = node->obj;
141
+ if(deque->size == 1) {
142
+ clear_deque(deque);
143
+ return obj;
144
+ }
145
+ deque->back->left->right = NULL;
146
+ deque->back = deque->back->left;
147
+ deque->size--;
148
+ return obj;
149
+ }
150
+
151
+ static VALUE deque_clear(VALUE self) {
152
+ deque *deque = get_deque_from_self(self);
153
+ clear_deque(deque);
154
+ return Qnil;
155
+ }
156
+
157
+ static VALUE deque_size(VALUE self) {
158
+ deque *deque = get_deque_from_self(self);
159
+ return INT2NUM(deque->size);
160
+ }
161
+
162
+ static VALUE deque_is_empty(VALUE self) {
163
+ deque *deque = get_deque_from_self(self);
164
+ return (deque->size == 0) ? Qtrue : Qfalse;
165
+ }
166
+
167
+ static VALUE deque_each_forward(VALUE self) {
168
+ deque *deque = get_deque_from_self(self);
169
+ deque_node *node = deque->front;
170
+ while(node) {
171
+ rb_yield(node->obj);
172
+ node = node->right;
173
+ }
174
+ return self;
175
+ }
176
+
177
+ static VALUE deque_each_backward(VALUE self) {
178
+ deque *deque = get_deque_from_self(self);
179
+ deque_node *node = deque->back;
180
+ while(node) {
181
+ rb_yield(node->obj);
182
+ node = node->left;
183
+ }
184
+ return self;
185
+ }
186
+
187
+ static VALUE deque_init(int argc, VALUE *argv, VALUE self)
188
+ {
189
+ int len, i;
190
+ VALUE ary;
191
+
192
+ if(argc == 0) {
193
+ return self;
194
+ }
195
+ else if(argc > 1) {
196
+ rb_raise(rb_eArgError, "wrong number of arguments");
197
+ }
198
+ else {
199
+ ary = rb_check_array_type(argv[0]);
200
+ if(!NIL_P(ary)) {
201
+ len = RARRAY_LEN(ary);
202
+ for (i = 0; i < len; i++) {
203
+ deque_push_back(self, RARRAY_PTR(ary)[i]);
204
+ }
205
+ }
206
+ }
207
+ return self;
208
+ }
209
+
210
+ static VALUE cDeque;
211
+ static VALUE mContainers;
212
+
213
+ void Init_CDeque() {
214
+ mContainers = rb_define_module("Containers");
215
+ cDeque = rb_define_class_under(mContainers, "CDeque", rb_cObject);
216
+ rb_define_alloc_func(cDeque, deque_alloc);
217
+ rb_define_method(cDeque, "initialize", deque_init, -1);
218
+ rb_define_method(cDeque, "push_front", deque_push_front, 1);
219
+ rb_define_method(cDeque, "push_back", deque_push_back, 1);
220
+ rb_define_method(cDeque, "clear", deque_clear, 0);
221
+ rb_define_method(cDeque, "front", deque_front, 0);
222
+ rb_define_method(cDeque, "back", deque_back, 0);
223
+ rb_define_method(cDeque, "pop_front", deque_pop_front, 0);
224
+ rb_define_method(cDeque, "pop_back", deque_pop_back, 0);
225
+ rb_define_method(cDeque, "size", deque_size, 0);
226
+ rb_define_alias(cDeque, "length", "size");
227
+ rb_define_method(cDeque, "empty?", deque_is_empty, 0);
228
+ rb_define_method(cDeque, "each_forward", deque_each_forward, 0);
229
+ rb_define_method(cDeque, "each_backward", deque_each_backward, 0);
230
+ rb_define_alias(cDeque, "each", "each_forward");
231
+ rb_define_alias(cDeque, "reverse_each", "each_backward");
232
+ rb_include_module(cDeque, rb_eval_string("Enumerable"));
233
+ }
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = "CDeque"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -1,4 +1,4 @@
1
1
  require 'mkmf'
2
- extension_name = "CTreeMap"
2
+ extension_name = "CRBTreeMap"
3
3
  dir_config(extension_name)
4
4
  create_makefile(extension_name)
@@ -122,6 +122,7 @@ static rbtree_node* fixup(rbtree_node *h) {
122
122
 
123
123
  return set_num_nodes(h);
124
124
  }
125
+
125
126
  static rbtree* create_rbtree(int (*compare_function)(VALUE, VALUE)) {
126
127
  rbtree *tree = ALLOC(rbtree);
127
128
  tree->black_height = 0;
@@ -146,11 +147,6 @@ static rbtree_node* insert(rbtree *tree, rbtree_node *node, VALUE key, VALUE val
146
147
  return new_node;
147
148
  }
148
149
 
149
- // Do a top-down breaking of 4-nodes
150
- if ( isred(node->left) && isred(node->right) ) {
151
- colorflip(node);
152
- }
153
-
154
150
  // Insert left or right, recursively
155
151
  cmp = tree->compare_function(key, node->key);
156
152
  if (cmp == 0) { node->value = value; }
@@ -160,7 +156,9 @@ static rbtree_node* insert(rbtree *tree, rbtree_node *node, VALUE key, VALUE val
160
156
  // Fix our tree to keep left-lean
161
157
  if (isred(node->right)) { node = rotate_left(node); }
162
158
  if (isred(node->left) && isred(node->left->left)) { node = rotate_right(node); }
163
-
159
+ if ( isred(node->left) && isred(node->right) ) {
160
+ colorflip(node);
161
+ }
164
162
  return set_num_nodes(node);
165
163
  }
166
164
 
@@ -191,34 +189,40 @@ static VALUE max_key(rbtree_node *node) {
191
189
  return max_key(node->right);
192
190
  }
193
191
 
194
- static rbtree_node* delete_min(rbtree_node *h) {
195
- if ( !(h->left) )
192
+ static rbtree_node* delete_min(rbtree_node *h, VALUE *deleted_value) {
193
+ if ( !h->left ) {
194
+ if(deleted_value)
195
+ *deleted_value = h->value;
196
+ free(h);
196
197
  return NULL;
198
+ }
197
199
 
198
200
  if ( !isred(h->left) && !isred(h->left->left) )
199
201
  h = move_red_left(h);
200
202
 
201
- h->left = delete_min(h->left);
203
+ h->left = delete_min(h->left, deleted_value);
202
204
 
203
205
  return fixup(h);
204
206
  }
205
207
 
206
- static rbtree_node* delete_max(rbtree_node *h) {
208
+ static rbtree_node* delete_max(rbtree_node *h, VALUE *deleted_value) {
207
209
  if ( isred(h->left) )
208
210
  h = rotate_right(h);
209
211
 
210
- if ( !(h->right) )
212
+ if ( !h->right ) {
213
+ *deleted_value = h->value;
214
+ free(h);
211
215
  return NULL;
216
+ }
212
217
 
213
218
  if ( !isred(h->right) && !isred(h->right->left) )
214
219
  h = move_red_right(h);
215
220
 
216
- h->right = delete_max(h->right);
221
+ h->right = delete_max(h->right, deleted_value);
217
222
 
218
223
  return fixup(h);
219
224
  }
220
225
 
221
-
222
226
  static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *deleted_value) {
223
227
  int cmp;
224
228
  VALUE minimum_key;
@@ -232,9 +236,11 @@ static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *de
232
236
  else {
233
237
  if ( isred(node->left) )
234
238
  node = rotate_right(node);
235
-
236
- if ( (cmp == 0) && !(node->right) ) {
239
+
240
+ cmp = tree->compare_function(key, node->key);
241
+ if ( (cmp == 0) && !node->right ) {
237
242
  *deleted_value = node->value;
243
+ free(node);
238
244
  return NULL;
239
245
  }
240
246
 
@@ -247,7 +253,7 @@ static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *de
247
253
  minimum_key = min_key(node->right);
248
254
  node->value = get(tree, node->right, minimum_key);
249
255
  node->key = minimum_key;
250
- node->right = delete_min(node->right);
256
+ node->right = delete_min(node->right, NULL);
251
257
  }
252
258
  else {
253
259
  node->right = delete(tree, node->right, key, deleted_value);
@@ -273,7 +279,6 @@ static rbtree* rbt_each(rbtree *tree, void (*each)(rbtree *tree, rbtree_node *no
273
279
  rbtree_each_node(tree, tree->root, each, arguments);
274
280
  return tree;
275
281
  }
276
-
277
282
 
278
283
  // Methods to be called in Ruby
279
284
 
@@ -298,7 +303,7 @@ static VALUE rbtree_alloc(VALUE klass) {
298
303
  return Data_Wrap_Struct(klass, NULL, rbtree_free, tree);
299
304
  }
300
305
 
301
- static VALUE rbtree_put(VALUE self, VALUE key, VALUE value) {
306
+ static VALUE rbtree_push(VALUE self, VALUE key, VALUE value) {
302
307
  rbtree *tree = get_tree_from_self(self);
303
308
  tree->root = insert(tree, tree->root, key, value);
304
309
  return value;
@@ -314,13 +319,19 @@ static VALUE rbtree_size(VALUE self) {
314
319
  return INT2NUM(size(tree->root));
315
320
  }
316
321
 
322
+ static VALUE rbtree_is_empty(VALUE self) {
323
+ rbtree *tree = get_tree_from_self(self);
324
+ return (tree->root ? Qfalse : Qtrue);
325
+ }
326
+
317
327
  static VALUE rbtree_height(VALUE self) {
318
328
  rbtree *tree = get_tree_from_self(self);
319
329
  return INT2NUM(height(tree->root));
320
330
  }
321
331
 
322
- static VALUE rbtree_contains(VALUE self, VALUE key) {
332
+ static VALUE rbtree_has_key(VALUE self, VALUE key) {
323
333
  rbtree *tree = get_tree_from_self(self);
334
+ if(!tree->root) { return Qfalse; }
324
335
  if(get(tree, tree->root, key) == Qnil)
325
336
  return Qfalse;
326
337
 
@@ -350,7 +361,41 @@ static VALUE rbtree_delete(VALUE self, VALUE key) {
350
361
  return Qnil;
351
362
 
352
363
  tree->root = delete(tree, tree->root, key, &deleted_value);
364
+ if(tree->root)
365
+ tree->root->color = BLACK;
366
+
367
+ if(deleted_value) {
368
+ return deleted_value;
369
+ }
370
+
371
+ return Qnil;
372
+ }
373
+
374
+ static VALUE rbtree_delete_min(VALUE self) {
375
+ VALUE deleted_value;
376
+ rbtree *tree = get_tree_from_self(self);
353
377
  if(!tree->root)
378
+ return Qnil;
379
+
380
+ tree->root = delete_min(tree->root, &deleted_value);
381
+ if(tree->root)
382
+ tree->root->color = BLACK;
383
+
384
+ if(deleted_value) {
385
+ return deleted_value;
386
+ }
387
+
388
+ return Qnil;
389
+ }
390
+
391
+ static VALUE rbtree_delete_max(VALUE self) {
392
+ VALUE deleted_value;
393
+ rbtree *tree = get_tree_from_self(self);
394
+ if(!tree->root)
395
+ return Qnil;
396
+
397
+ tree->root = delete_max(tree->root, &deleted_value);
398
+ if(tree->root)
354
399
  tree->root->color = BLACK;
355
400
 
356
401
  if(deleted_value) {
@@ -373,23 +418,26 @@ static VALUE rbtree_each(VALUE self) {
373
418
  static VALUE cRBTree;
374
419
  static VALUE mContainers;
375
420
 
376
- void Init_CTreeMap() {
421
+ void Init_CRBTreeMap() {
377
422
  id_compare_operator = rb_intern("<=>");
378
423
 
379
424
  mContainers = rb_define_module("Containers");
380
- cRBTree = rb_define_class_under(mContainers, "CTreeMap", rb_cObject);
425
+ cRBTree = rb_define_class_under(mContainers, "CRBTreeMap", rb_cObject);
381
426
  rb_define_alloc_func(cRBTree, rbtree_alloc);
382
427
  rb_define_method(cRBTree, "initialize", rbtree_init, 0);
383
- rb_define_method(cRBTree, "put", rbtree_put, 2);
384
- rb_define_alias(cRBTree, "[]=", "put");
428
+ rb_define_method(cRBTree, "push", rbtree_push, 2);
429
+ rb_define_alias(cRBTree, "[]=", "push");
385
430
  rb_define_method(cRBTree, "size", rbtree_size, 0);
431
+ rb_define_method(cRBTree, "empty?", rbtree_is_empty, 0);
386
432
  rb_define_method(cRBTree, "height", rbtree_height, 0);
387
433
  rb_define_method(cRBTree, "min_key", rbtree_min_key, 0);
388
434
  rb_define_method(cRBTree, "max_key", rbtree_max_key, 0);
435
+ rb_define_method(cRBTree, "delete_min", rbtree_delete_min, 0);
436
+ rb_define_method(cRBTree, "delete_max", rbtree_delete_max, 0);
389
437
  rb_define_method(cRBTree, "each", rbtree_each, 0);
390
438
  rb_define_method(cRBTree, "get", rbtree_get, 1);
391
439
  rb_define_alias(cRBTree, "[]", "get");
392
- rb_define_method(cRBTree, "contains?", rbtree_contains, 1);
440
+ rb_define_method(cRBTree, "has_key?", rbtree_has_key, 1);
393
441
  rb_define_method(cRBTree, "delete", rbtree_delete, 1);
394
442
  rb_include_module(cRBTree, rb_eval_string("Enumerable"));
395
- }
443
+ }