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