kanwei-algorithms 0.2.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 (42) hide show
  1. data/History.txt +168 -0
  2. data/Manifest +41 -0
  3. data/README.markdown +92 -0
  4. data/Rakefile +31 -0
  5. data/algorithms.gemspec +32 -0
  6. data/benchmarks/deque.rb +17 -0
  7. data/benchmarks/sorts.rb +34 -0
  8. data/benchmarks/treemaps.rb +36 -0
  9. data/ext/containers/deque/deque.c +247 -0
  10. data/ext/containers/deque/extconf.rb +4 -0
  11. data/ext/containers/rbtree_map/extconf.rb +4 -0
  12. data/ext/containers/rbtree_map/rbtree.c +473 -0
  13. data/ext/containers/splaytree_map/extconf.rb +4 -0
  14. data/ext/containers/splaytree_map/splaytree.c +370 -0
  15. data/lib/algorithms/search.rb +84 -0
  16. data/lib/algorithms/sort.rb +238 -0
  17. data/lib/algorithms.rb +67 -0
  18. data/lib/containers/deque.rb +171 -0
  19. data/lib/containers/heap.rb +486 -0
  20. data/lib/containers/kd_tree.rb +87 -0
  21. data/lib/containers/priority_queue.rb +113 -0
  22. data/lib/containers/queue.rb +68 -0
  23. data/lib/containers/rb_tree_map.rb +398 -0
  24. data/lib/containers/splay_tree_map.rb +269 -0
  25. data/lib/containers/stack.rb +67 -0
  26. data/lib/containers/suffix_array.rb +68 -0
  27. data/lib/containers/trie.rb +182 -0
  28. data/spec/deque_gc_mark_spec.rb +18 -0
  29. data/spec/deque_spec.rb +108 -0
  30. data/spec/heap_spec.rb +126 -0
  31. data/spec/kd_tree_spec.rb +4 -0
  32. data/spec/priority_queue_spec.rb +75 -0
  33. data/spec/queue_spec.rb +61 -0
  34. data/spec/rb_tree_map_gc_mark_spec.rb +25 -0
  35. data/spec/rb_tree_map_spec.rb +123 -0
  36. data/spec/search_spec.rb +28 -0
  37. data/spec/sort_spec.rb +28 -0
  38. data/spec/splay_tree_map_spec.rb +102 -0
  39. data/spec/stack_spec.rb +60 -0
  40. data/spec/suffix_array_spec.rb +40 -0
  41. data/spec/trie_spec.rb +59 -0
  42. metadata +120 -0
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = "CSplayTreeMap"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -0,0 +1,370 @@
1
+ #include "ruby.h"
2
+
3
+ typedef struct struct_splaytree_node {
4
+ VALUE key;
5
+ VALUE value;
6
+ struct struct_splaytree_node *left;
7
+ struct struct_splaytree_node *right;
8
+ } splaytree_node;
9
+
10
+ typedef struct {
11
+ int (*compare_function)(VALUE key1, VALUE key2);
12
+ int size;
13
+ splaytree_node *root;
14
+ splaytree_node *header;
15
+ } splaytree;
16
+
17
+ static void recursively_free_nodes(splaytree_node *node) {
18
+ if(node) {
19
+ recursively_free_nodes(node->left);
20
+ recursively_free_nodes(node->right);
21
+ free(node);
22
+ }
23
+ return;
24
+ }
25
+
26
+ static splaytree* get_tree_from_self(VALUE self) {
27
+ splaytree *tree;
28
+ Data_Get_Struct(self, splaytree, tree);
29
+ return tree;
30
+ }
31
+
32
+ static void splay(splaytree *tree, VALUE key) {
33
+ int cmp, cmp2;
34
+ splaytree_node *l, *r, *t, *y;
35
+
36
+ l = tree->header;
37
+ r = tree->header;
38
+ t = tree->root;
39
+
40
+ tree->header->left = NULL;
41
+ tree->header->right = NULL;
42
+
43
+ while(1) {
44
+ cmp = tree->compare_function(key, t->key);
45
+ if (cmp == -1) {
46
+ if (!(t->left)) break;
47
+ cmp2 = tree->compare_function(key, t->left->key);
48
+ if (cmp2 == -1) {
49
+ y = t->left;
50
+ t->left = y->right;
51
+ y->right = t;
52
+ t = y;
53
+ if (!(t->left)) break;
54
+ }
55
+ r->left = t;
56
+ r = t;
57
+ t = t->left;
58
+ }
59
+ else if (cmp == 1) {
60
+ if (!(t->right)) break;
61
+ cmp2 = tree->compare_function(key, t->right->key);
62
+ if (cmp2 == 1) {
63
+ y = t->right;
64
+ t->right = y->left;
65
+ y->left = t;
66
+ t = y;
67
+ if (!(t->right)) break;
68
+ }
69
+ l->right = t;
70
+ l = t;
71
+ t = t->right;
72
+ } else {
73
+ break;
74
+ }
75
+ }
76
+ l->right = t->left;
77
+ r->left = t->right;
78
+ t->left = tree->header->right;
79
+ t->right = tree->header->left;
80
+ tree->root = t;
81
+ }
82
+
83
+ static int height(splaytree_node *h) {
84
+ int left_height, right_height;
85
+
86
+ if(!h) { return 0; }
87
+
88
+ left_height = 1 + height(h->left);
89
+ right_height = 1 + height(h->right);
90
+
91
+ return left_height > right_height ? left_height : right_height;
92
+ }
93
+
94
+ static splaytree* create_splaytree(int (*compare_function)(VALUE, VALUE)) {
95
+ splaytree *tree = ALLOC(splaytree);
96
+ tree->compare_function = compare_function;
97
+ tree->root = NULL;
98
+ tree->size = 0;
99
+ tree->header = ALLOC(splaytree_node);
100
+ return tree;
101
+ }
102
+
103
+ static splaytree_node* create_node(VALUE key, VALUE value) {
104
+ splaytree_node *new_node = ALLOC(splaytree_node);
105
+ new_node->key = key;
106
+ new_node->value = value;
107
+ new_node->left = NULL;
108
+ new_node->right = NULL;
109
+ return new_node;
110
+ }
111
+
112
+ static void insert(splaytree *tree, VALUE key, VALUE value) {
113
+ int cmp;
114
+ splaytree_node *new_node;
115
+
116
+ if (!(tree->root)) {
117
+ new_node = create_node(key, value);
118
+ tree->root = new_node;
119
+ tree->size += 1;
120
+ return;
121
+ }
122
+
123
+ splay(tree, key);
124
+ cmp = tree->compare_function(key, tree->root->key);
125
+ if (cmp == 0) {
126
+ tree->root->value = value;
127
+ return;
128
+ } else {
129
+ new_node = create_node(key, value);
130
+ if (cmp == -1) {
131
+ new_node->left = tree->root->left;
132
+ new_node->right = tree->root;
133
+ tree->root->left = NULL;
134
+ } else { /* cmp == 1 */
135
+ new_node->right = tree->root->right;
136
+ new_node->left = tree->root;
137
+ tree->root->right = NULL;
138
+ }
139
+ tree->root = new_node;
140
+ tree->size += 1;
141
+ }
142
+ }
143
+
144
+ static VALUE get(splaytree *tree, VALUE key) {
145
+ int cmp;
146
+ if (!tree->root)
147
+ return Qnil;
148
+
149
+ splay(tree, key);
150
+ cmp = tree->compare_function(key, tree->root->key);
151
+ if (cmp == 0) {
152
+ return tree->root->value;
153
+ }
154
+ return Qnil;
155
+ }
156
+
157
+ static VALUE delete(splaytree *tree, VALUE key) {
158
+ int cmp;
159
+ splaytree_node *x, *deleted_root;
160
+ VALUE deleted;
161
+
162
+ splay(tree, key);
163
+ cmp = tree->compare_function(key, tree->root->key);
164
+ if (cmp == 0) {
165
+ deleted = tree->root->value;
166
+ deleted_root = tree->root;
167
+ if (!(tree->root->left)) {
168
+ tree->root = tree->root->right;
169
+ } else {
170
+ x = tree->root->right;
171
+ tree->root = tree->root->left;
172
+ splay(tree, key);
173
+ tree->root->right = x;
174
+ }
175
+ free(deleted_root);
176
+ tree->size -= 1;
177
+ return deleted;
178
+ }
179
+ return Qnil;
180
+ }
181
+
182
+ static splaytree* splaytree_each_node(splaytree *tree, splaytree_node *node, void (*each)(splaytree *tree_, splaytree_node *node_, void* args), void* arguments) {
183
+ if (!node)
184
+ return NULL;
185
+
186
+ if (node->left)
187
+ splaytree_each_node(tree, node->left, each, arguments);
188
+
189
+ (*each)(tree, node, arguments);
190
+
191
+ if (node->right)
192
+ splaytree_each_node(tree, node->right, each, arguments);
193
+ return tree;
194
+ }
195
+
196
+ static splaytree* splay_each(splaytree *tree, void (*each)(splaytree *tree, splaytree_node *node, void *args), void* arguments) {
197
+ if (tree->root)
198
+ splaytree_each_node(tree, tree->root, each, arguments);
199
+ return tree;
200
+ }
201
+
202
+ // Methods to be called in Ruby
203
+
204
+ static int id_compare_operator;
205
+
206
+ static int splaytree_compare_function(VALUE a, VALUE b) {
207
+ if (a == b) return 0;
208
+ if (FIXNUM_P(a) && FIXNUM_P(b)) {
209
+ long x = FIX2LONG(a), y = FIX2LONG(b);
210
+ if (x == y) return 0;
211
+ if (x > y) return 1;
212
+ return -1;
213
+ }
214
+ if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString &&
215
+ TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) {
216
+ return rb_str_cmp(a, b);
217
+ }
218
+ return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
219
+ }
220
+
221
+ static VALUE splaytree_init(VALUE self)
222
+ {
223
+ return self;
224
+ }
225
+
226
+ static void recursively_mark_nodes(splaytree_node *node) {
227
+ if(node) {
228
+ rb_gc_mark(node->key);
229
+ rb_gc_mark(node->value);
230
+ recursively_mark_nodes(node->left);
231
+ recursively_mark_nodes(node->right);
232
+ }
233
+ }
234
+
235
+ static void splaytree_mark(void *ptr) {
236
+ if (ptr) {
237
+ splaytree *tree = ptr;
238
+ recursively_mark_nodes(tree->root);
239
+ }
240
+ }
241
+
242
+ static void splaytree_free(void *ptr) {
243
+ if (ptr) {
244
+ splaytree *tree = ptr;
245
+ recursively_free_nodes(tree->root);
246
+ free(tree->header);
247
+ free(tree);
248
+ }
249
+ }
250
+
251
+ static VALUE splaytree_alloc(VALUE klass) {
252
+ splaytree *tree = create_splaytree(&splaytree_compare_function);
253
+ return Data_Wrap_Struct(klass, splaytree_mark, splaytree_free, tree);
254
+ }
255
+
256
+ static VALUE splaytree_push(VALUE self, VALUE key, VALUE value) {
257
+ splaytree *tree = get_tree_from_self(self);
258
+ insert(tree, key, value);
259
+ return value;
260
+ }
261
+
262
+ static VALUE splaytree_get(VALUE self, VALUE key) {
263
+ splaytree *tree = get_tree_from_self(self);
264
+ return get(tree, key);
265
+ }
266
+
267
+ static VALUE splaytree_size(VALUE self) {
268
+ splaytree *tree = get_tree_from_self(self);
269
+ return INT2NUM(tree->size);
270
+ }
271
+
272
+ static VALUE splaytree_is_empty(VALUE self) {
273
+ splaytree *tree = get_tree_from_self(self);
274
+ return (tree->root ? Qfalse : Qtrue);
275
+ }
276
+
277
+ static VALUE splaytree_height(VALUE self) {
278
+ splaytree *tree = get_tree_from_self(self);
279
+ return INT2NUM(height(tree->root));
280
+ }
281
+
282
+ static VALUE splaytree_has_key(VALUE self, VALUE key) {
283
+ splaytree *tree = get_tree_from_self(self);
284
+ if(!tree->root) { return Qfalse; }
285
+ if(get(tree, key) == Qnil)
286
+ return Qfalse;
287
+
288
+ return Qtrue;
289
+ }
290
+
291
+ static VALUE splaytree_min_key(VALUE self) {
292
+ splaytree *tree = get_tree_from_self(self);
293
+ splaytree_node *node;
294
+
295
+ if(!tree->root)
296
+ return Qnil;
297
+
298
+ node = tree->root;
299
+ while (node->left)
300
+ node = node->left;
301
+
302
+ return node->key;
303
+ }
304
+
305
+ static VALUE splaytree_max_key(VALUE self) {
306
+ splaytree *tree = get_tree_from_self(self);
307
+ splaytree_node *node;
308
+
309
+ if(!tree->root)
310
+ return Qnil;
311
+
312
+ node = tree->root;
313
+ while (node->right)
314
+ node = node->right;
315
+
316
+ return node->key;
317
+ }
318
+
319
+ static VALUE splaytree_delete(VALUE self, VALUE key) {
320
+ splaytree *tree = get_tree_from_self(self);
321
+ if(!tree->root)
322
+ return Qnil;
323
+
324
+ return delete(tree, key);
325
+ }
326
+
327
+ static VALUE splaytree_clear(VALUE self) {
328
+ splaytree *tree = get_tree_from_self(self);
329
+ recursively_free_nodes(tree->root);
330
+ tree->root = NULL;
331
+ tree->size = 0;
332
+
333
+ return Qnil;
334
+ }
335
+
336
+ static void splaytree_each_helper(splaytree *tree, splaytree_node *node, void *args) {
337
+ rb_yield(rb_ary_new3(2, node->key, node->value));
338
+ };
339
+
340
+ static VALUE splaytree_each(VALUE self) {
341
+ splaytree *tree = get_tree_from_self(self);
342
+ splay_each(tree, &splaytree_each_helper, NULL);
343
+ return self;
344
+ }
345
+
346
+ static VALUE CSplayTree;
347
+ static VALUE mContainers;
348
+
349
+ void Init_CSplayTreeMap() {
350
+ id_compare_operator = rb_intern("<=>");
351
+
352
+ mContainers = rb_define_module("Containers");
353
+ CSplayTree = rb_define_class_under(mContainers, "CSplayTreeMap", rb_cObject);
354
+ rb_define_alloc_func(CSplayTree, splaytree_alloc);
355
+ rb_define_method(CSplayTree, "initialize", splaytree_init, 0);
356
+ rb_define_method(CSplayTree, "push", splaytree_push, 2);
357
+ rb_define_method(CSplayTree, "clear", splaytree_clear, 0);
358
+ rb_define_alias(CSplayTree, "[]=", "push");
359
+ rb_define_method(CSplayTree, "size", splaytree_size, 0);
360
+ rb_define_method(CSplayTree, "empty?", splaytree_is_empty, 0);
361
+ rb_define_method(CSplayTree, "height", splaytree_height, 0);
362
+ rb_define_method(CSplayTree, "min_key", splaytree_min_key, 0);
363
+ rb_define_method(CSplayTree, "max_key", splaytree_max_key, 0);
364
+ rb_define_method(CSplayTree, "each", splaytree_each, 0);
365
+ rb_define_method(CSplayTree, "get", splaytree_get, 1);
366
+ rb_define_alias(CSplayTree, "[]", "get");
367
+ rb_define_method(CSplayTree, "has_key?", splaytree_has_key, 1);
368
+ rb_define_method(CSplayTree, "delete", splaytree_delete, 1);
369
+ rb_include_module(CSplayTree, rb_eval_string("Enumerable"));
370
+ }
@@ -0,0 +1,84 @@
1
+ =begin rdoc
2
+ This module implements search algorithms. Documentation is provided for each algorithm.
3
+
4
+ =end
5
+ module Algorithms::Search
6
+ # Binary Search: This search finds an item in log(n) time provided that the container is already sorted.
7
+ # The method returns the item if it is found, or nil if it is not. If there are duplicates, the first one
8
+ # found is returned, and this is not guaranteed to be the smallest or largest item.
9
+ #
10
+ # Complexity: O(lg N)
11
+ #
12
+ # Algorithms::Search.binary_search([1, 2, 3], 1) #=> 1
13
+ # Algorithms::Search.binary_search([1, 2, 3], 4) #=> nil
14
+ def self.binary_search(container, item)
15
+ return nil if item.nil?
16
+ low = 0
17
+ high = container.size - 1
18
+ while low <= high
19
+ mid = (low + high) / 2
20
+ val = container[mid]
21
+ if val > item
22
+ high = mid - 1
23
+ elsif val < item
24
+ low = mid + 1
25
+ else
26
+ return val
27
+ end
28
+ end
29
+ nil
30
+ end
31
+
32
+ # Knuth-Morris-Pratt Algorithm substring search algorithm: Efficiently finds the starting position of a
33
+ # substring in a string. The algorithm calculates the best position to resume searching from if a failure
34
+ # occurs.
35
+ #
36
+ # The method returns the index of the starting position in the string where the substring is found. If there
37
+ # is no match, nil is returned.
38
+ #
39
+ # Complexity: O(n + k), where n is the length of the string and k is the length of the substring.
40
+ #
41
+ # Algorithms::Search.kmp_search("ABC ABCDAB ABCDABCDABDE", "ABCDABD") #=> 15
42
+ # Algorithms::Search.kmp_search("ABC ABCDAB ABCDABCDABDE", "ABCDEF") #=> nil
43
+ def self.kmp_search(string, substring)
44
+ return nil if string.nil? or substring.nil?
45
+
46
+ # create failure function table
47
+ pos = 2
48
+ cnd = 0
49
+ failure_table = [-1, 0]
50
+ while pos < substring.length
51
+ if substring[pos - 1] == substring[cnd]
52
+ failure_table[pos] = cnd + 1
53
+ pos += 1
54
+ cnd += 1
55
+ elsif cnd > 0
56
+ cnd = failure_table[cnd]
57
+ else
58
+ failure_table[pos] = 0
59
+ pos += 1
60
+ end
61
+ end
62
+
63
+ m = i = 0
64
+ while m + i < string.length
65
+ if substring[i] == string[m + i]
66
+ i += 1
67
+ return m if i == substring.length
68
+ else
69
+ m = m + i - failure_table[i]
70
+ i = failure_table[i] if i > 0
71
+ end
72
+ end
73
+ return nil
74
+ end
75
+
76
+ # Allows kmp_search to be called as an instance method in classes that include the Search module.
77
+ #
78
+ # class String; include Algorithms::Search; end
79
+ # "ABC ABCDAB ABCDABCDABDE".kmp_search("ABCDABD") #=> 15
80
+ def kmp_search(substring)
81
+ Algorithms::Search.kmp_search(self, substring)
82
+ end
83
+
84
+ end