victory 0.0.0 → 0.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 +4 -4
- data/.gitignore +5 -0
- data/.rubocop.yml +11 -1
- data/README.md +4 -6
- data/Rakefile +11 -4
- data/USAGE.md +159 -0
- data/ext/algorithms/string/LICENSE.md +21 -0
- data/ext/algorithms/string/extconf.rb +4 -0
- data/ext/algorithms/string/string.c +68 -0
- data/ext/containers/bst/LICENSE.md +21 -0
- data/ext/containers/bst/bst.c +247 -0
- data/ext/containers/bst/extconf.rb +4 -0
- data/ext/containers/deque/LICENSE.md +21 -0
- data/ext/containers/deque/deque.c +247 -0
- data/ext/containers/deque/extconf.rb +4 -0
- data/ext/containers/rbtree_map/LICENSE.md +21 -0
- data/ext/containers/rbtree_map/extconf.rb +4 -0
- data/ext/containers/rbtree_map/rbtree.c +498 -0
- data/ext/containers/splaytree_map/LICENSE.md +21 -0
- data/ext/containers/splaytree_map/extconf.rb +4 -0
- data/ext/containers/splaytree_map/splaytree.c +419 -0
- data/ext/containers/xor_list/extconf.rb +4 -0
- data/ext/containers/xor_list/xor_list.c +122 -0
- data/lib/algorithms/search.rb +104 -0
- data/lib/algorithms/sort.rb +389 -0
- data/lib/algorithms/string.rb +29 -0
- data/lib/containers/deque.rb +193 -0
- data/lib/containers/heap.rb +524 -0
- data/lib/containers/kd_tree.rb +131 -0
- data/lib/containers/list.rb +81 -0
- data/lib/containers/prefix_tree.rb +61 -0
- data/lib/containers/priority_queue.rb +135 -0
- data/lib/containers/queue.rb +89 -0
- data/lib/containers/rb_tree_map.rb +420 -0
- data/lib/containers/splay_tree_map.rb +290 -0
- data/lib/containers/stack.rb +88 -0
- data/lib/containers/suffix_array.rb +92 -0
- data/lib/containers/trie.rb +204 -0
- data/lib/containers/tuple.rb +20 -0
- data/lib/victory/version.rb +1 -1
- data/lib/victory.rb +8 -1
- data/victory.gemspec +12 -3
- metadata +73 -12
- data/.idea/encodings.xml +0 -4
- data/.idea/misc.xml +0 -7
- data/.idea/modules.xml +0 -8
- data/.idea/victory.iml +0 -13
- data/.idea/workspace.xml +0 -233
- data/ext/victory/extconf.rb +0 -3
- data/ext/victory/victory.c +0 -9
- data/ext/victory/victory.h +0 -6
@@ -0,0 +1,419 @@
|
|
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
|
+
xfree(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
|
+
xfree(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 VALUE 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
|
+
xfree(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
|
+
xfree(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
|
+
|
398
|
+
void Init_CSplayTreeMap() {
|
399
|
+
id_compare_operator = rb_intern("<=>");
|
400
|
+
|
401
|
+
mContainers = rb_define_module("Containers");
|
402
|
+
CSplayTree = rb_define_class_under(mContainers, "CSplayTreeMap", rb_cObject);
|
403
|
+
rb_define_alloc_func(CSplayTree, splaytree_alloc);
|
404
|
+
rb_define_method(CSplayTree, "initialize", splaytree_init, 0);
|
405
|
+
rb_define_method(CSplayTree, "push", splaytree_push, 2);
|
406
|
+
rb_define_method(CSplayTree, "clear", splaytree_clear, 0);
|
407
|
+
rb_define_alias(CSplayTree, "[]=", "push");
|
408
|
+
rb_define_method(CSplayTree, "size", splaytree_size, 0);
|
409
|
+
rb_define_method(CSplayTree, "empty?", splaytree_is_empty, 0);
|
410
|
+
rb_define_method(CSplayTree, "height", splaytree_height, 0);
|
411
|
+
rb_define_method(CSplayTree, "min_key", splaytree_min_key, 0);
|
412
|
+
rb_define_method(CSplayTree, "max_key", splaytree_max_key, 0);
|
413
|
+
rb_define_method(CSplayTree, "each", splaytree_each, 0);
|
414
|
+
rb_define_method(CSplayTree, "get", splaytree_get, 1);
|
415
|
+
rb_define_alias(CSplayTree, "[]", "get");
|
416
|
+
rb_define_method(CSplayTree, "has_key?", splaytree_has_key, 1);
|
417
|
+
rb_define_method(CSplayTree, "delete", splaytree_delete, 1);
|
418
|
+
rb_include_module(CSplayTree, rb_eval_string("Enumerable"));
|
419
|
+
}
|
@@ -0,0 +1,122 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
typedef struct struct_node {
|
4
|
+
VALUE obj;
|
5
|
+
struct struct_node *npx; // XOR of next and previous
|
6
|
+
} node;
|
7
|
+
|
8
|
+
typedef struct {
|
9
|
+
unsigned int size;
|
10
|
+
node *front;
|
11
|
+
node *back;
|
12
|
+
} xor_list;
|
13
|
+
|
14
|
+
node* xor(node *a, node *b)
|
15
|
+
{
|
16
|
+
return (node*) ((uintptr_t) (a) ^ (uintptr_t) (b));
|
17
|
+
}
|
18
|
+
|
19
|
+
static xor_list* get_xor_list(VALUE self) {
|
20
|
+
xor_list *list;
|
21
|
+
Data_Get_Struct(self, xor_list, list);
|
22
|
+
return list;
|
23
|
+
}
|
24
|
+
|
25
|
+
static xor_list* create_xor_list() {
|
26
|
+
xor_list *list = ALLOC(xor_list);
|
27
|
+
list->size = 0;
|
28
|
+
list->front = NULL;
|
29
|
+
list->back = NULL;
|
30
|
+
return list;
|
31
|
+
}
|
32
|
+
|
33
|
+
static void xor_list_mark(void *ptr) {
|
34
|
+
node *prev = NULL, *next = NULL;
|
35
|
+
if (ptr) {
|
36
|
+
xor_list *list = ptr;
|
37
|
+
node *current = list->front;
|
38
|
+
while(current) {
|
39
|
+
rb_gc_mark(current->obj);
|
40
|
+
next = xor(prev, current->npx);
|
41
|
+
prev = current;
|
42
|
+
current = next;
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
void free_nodes(node *current) {
|
48
|
+
node *prev = NULL, *next = NULL;
|
49
|
+
while(current) {
|
50
|
+
xfree(current);
|
51
|
+
next = xor(prev, current->npx);
|
52
|
+
prev = current;
|
53
|
+
current = next;
|
54
|
+
}
|
55
|
+
return;
|
56
|
+
}
|
57
|
+
|
58
|
+
static void xor_list_free(void *ptr) {
|
59
|
+
if (ptr) {
|
60
|
+
xor_list *list = ptr;
|
61
|
+
free_nodes(list->front);
|
62
|
+
xfree(list);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
static VALUE xor_list_alloc(VALUE klass) {
|
67
|
+
xor_list *list = create_xor_list();
|
68
|
+
return Data_Wrap_Struct(klass, xor_list_mark, xor_list_free, list);
|
69
|
+
}
|
70
|
+
|
71
|
+
static node* create_node(VALUE obj) {
|
72
|
+
node *n = ALLOC(node);
|
73
|
+
n->obj = obj;
|
74
|
+
n->npx = NULL;
|
75
|
+
return n;
|
76
|
+
}
|
77
|
+
|
78
|
+
static VALUE xor_list_init(VALUE self)
|
79
|
+
{
|
80
|
+
return self;
|
81
|
+
}
|
82
|
+
|
83
|
+
static VALUE xor_list_push_front(VALUE self, VALUE obj) {
|
84
|
+
xor_list *list = get_xor_list(self);
|
85
|
+
node *current = create_node(obj);
|
86
|
+
if(list->front) {
|
87
|
+
current->npx = xor(NULL, list->front);
|
88
|
+
list->front->npx = xor(current, xor(NULL, list->front->npx));
|
89
|
+
}
|
90
|
+
else {
|
91
|
+
list->back = current;
|
92
|
+
}
|
93
|
+
list->front = current;
|
94
|
+
list->size++;
|
95
|
+
return obj;
|
96
|
+
}
|
97
|
+
|
98
|
+
static VALUE xor_list_each(VALUE self) {
|
99
|
+
xor_list *list = get_xor_list(self);
|
100
|
+
node *current = list->front;
|
101
|
+
node *prev = NULL, *next = NULL;
|
102
|
+
while(current) {
|
103
|
+
rb_yield(current->obj);
|
104
|
+
next = xor(prev, current->npx);
|
105
|
+
prev = current;
|
106
|
+
current = next;
|
107
|
+
}
|
108
|
+
return self;
|
109
|
+
}
|
110
|
+
|
111
|
+
static VALUE list;
|
112
|
+
static VALUE containers;
|
113
|
+
|
114
|
+
void Init_XORList() {
|
115
|
+
containers = rb_define_module("Containers");
|
116
|
+
list = rb_define_class_under(containers, "XORList", rb_cObject);
|
117
|
+
rb_define_alloc_func(list, xor_list_alloc);
|
118
|
+
rb_define_method(list, "initialize", xor_list_init, 0);
|
119
|
+
rb_define_method(list, "push_front", xor_list_push_front, 1);
|
120
|
+
rb_define_method(list, "each", xor_list_each, 0);
|
121
|
+
rb_include_module(list, rb_eval_string("Enumerable"));
|
122
|
+
}
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# rdoc
|
2
|
+
# This module implements search algorithms. Documentation is provided for each algorithm.
|
3
|
+
#
|
4
|
+
# MIT License
|
5
|
+
#
|
6
|
+
# Copyright (c) 2009 Kanwei Li
|
7
|
+
#
|
8
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
+
# of this software and associated documentation files (the "Software"), to deal
|
10
|
+
# in the Software without restriction, including without limitation the rights
|
11
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
+
# copies of the Software, and to permit persons to whom the Software is
|
13
|
+
# furnished to do so, subject to the following conditions:
|
14
|
+
#
|
15
|
+
# The above copyright notice and this permission notice shall be included in all
|
16
|
+
# copies or substantial portions of the Software.
|
17
|
+
#
|
18
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
24
|
+
# SOFTWARE.
|
25
|
+
module Algorithms::Search
|
26
|
+
# Binary Search: This search finds an item in log(n) time provided that the container is already sorted.
|
27
|
+
# The method returns the item if it is found, or nil if it is not. If there are duplicates, the first one
|
28
|
+
# found is returned, and this is not guaranteed to be the smallest or largest item.
|
29
|
+
#
|
30
|
+
# Complexity: O(lg N)
|
31
|
+
#
|
32
|
+
# Algorithms::Search.binary_search([1, 2, 3], 1) #=> 1
|
33
|
+
# Algorithms::Search.binary_search([1, 2, 3], 4) #=> nil
|
34
|
+
def self.binary_search(container, item)
|
35
|
+
return nil if item.nil?
|
36
|
+
low = 0
|
37
|
+
high = container.size - 1
|
38
|
+
while low <= high
|
39
|
+
mid = (low + high) / 2
|
40
|
+
val = container[mid]
|
41
|
+
if val > item
|
42
|
+
high = mid - 1
|
43
|
+
elsif val < item
|
44
|
+
low = mid + 1
|
45
|
+
else
|
46
|
+
return val
|
47
|
+
end
|
48
|
+
end
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# Knuth-Morris-Pratt Algorithm substring search algorithm: Efficiently finds the starting position of a
|
53
|
+
# substring in a string. The algorithm calculates the best position to resume searching from if a failure
|
54
|
+
# occurs.
|
55
|
+
#
|
56
|
+
# The method returns the index of the starting position in the string where the substring is found. If there
|
57
|
+
# is no match, nil is returned.
|
58
|
+
#
|
59
|
+
# Complexity: O(n + k), where n is the length of the string and k is the length of the substring.
|
60
|
+
#
|
61
|
+
# Algorithms::Search.kmp_search("ABC ABCDAB ABCDABCDABDE", "ABCDABD") #=> 15
|
62
|
+
# Algorithms::Search.kmp_search("ABC ABCDAB ABCDABCDABDE", "ABCDEF") #=> nil
|
63
|
+
def self.kmp_search(string, substring)
|
64
|
+
return nil if string.nil? or substring.nil?
|
65
|
+
|
66
|
+
# create failure function table
|
67
|
+
pos = 2
|
68
|
+
cnd = 0
|
69
|
+
failure_table = [-1, 0]
|
70
|
+
while pos < substring.length
|
71
|
+
if substring[pos - 1] == substring[cnd]
|
72
|
+
failure_table[pos] = cnd + 1
|
73
|
+
pos += 1
|
74
|
+
cnd += 1
|
75
|
+
elsif cnd > 0
|
76
|
+
cnd = failure_table[cnd]
|
77
|
+
else
|
78
|
+
failure_table[pos] = 0
|
79
|
+
pos += 1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
m = i = 0
|
84
|
+
while m + i < string.length
|
85
|
+
if substring[i] == string[m + i]
|
86
|
+
i += 1
|
87
|
+
return m if i == substring.length
|
88
|
+
else
|
89
|
+
m = m + i - failure_table[i]
|
90
|
+
i = failure_table[i] if i > 0
|
91
|
+
end
|
92
|
+
end
|
93
|
+
return nil
|
94
|
+
end
|
95
|
+
|
96
|
+
# Allows kmp_search to be called as an instance method in classes that include the Search module.
|
97
|
+
#
|
98
|
+
# class String; include Algorithms::Search; end
|
99
|
+
# "ABC ABCDAB ABCDABCDABDE".kmp_search("ABCDABD") #=> 15
|
100
|
+
def kmp_search(substring)
|
101
|
+
Algorithms::Search.kmp_search(self, substring)
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|