stakach-algorithms 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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