amorim-algorithms 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.markdown +193 -0
  3. data/Gemfile +9 -0
  4. data/Manifest +51 -0
  5. data/README.markdown +87 -0
  6. data/Rakefile +22 -0
  7. data/algorithms.gemspec +23 -0
  8. data/benchmarks/deque.rb +17 -0
  9. data/benchmarks/sorts.rb +34 -0
  10. data/benchmarks/treemaps.rb +51 -0
  11. data/ext/algorithms/string/extconf.rb +4 -0
  12. data/ext/algorithms/string/string.c +68 -0
  13. data/ext/containers/bst/bst.c +247 -0
  14. data/ext/containers/bst/extconf.rb +4 -0
  15. data/ext/containers/deque/deque.c +247 -0
  16. data/ext/containers/deque/extconf.rb +4 -0
  17. data/ext/containers/rbtree_map/extconf.rb +4 -0
  18. data/ext/containers/rbtree_map/rbtree.c +498 -0
  19. data/ext/containers/splaytree_map/extconf.rb +4 -0
  20. data/ext/containers/splaytree_map/splaytree.c +419 -0
  21. data/lib/algorithms.rb +66 -0
  22. data/lib/algorithms/search.rb +84 -0
  23. data/lib/algorithms/sort.rb +368 -0
  24. data/lib/algorithms/string.rb +9 -0
  25. data/lib/containers/deque.rb +171 -0
  26. data/lib/containers/heap.rb +499 -0
  27. data/lib/containers/kd_tree.rb +110 -0
  28. data/lib/containers/priority_queue.rb +113 -0
  29. data/lib/containers/queue.rb +68 -0
  30. data/lib/containers/rb_tree_map.rb +398 -0
  31. data/lib/containers/splay_tree_map.rb +269 -0
  32. data/lib/containers/stack.rb +67 -0
  33. data/lib/containers/suffix_array.rb +68 -0
  34. data/lib/containers/trie.rb +182 -0
  35. data/spec/bst_gc_mark_spec.rb +25 -0
  36. data/spec/bst_spec.rb +25 -0
  37. data/spec/deque_gc_mark_spec.rb +18 -0
  38. data/spec/deque_spec.rb +108 -0
  39. data/spec/heap_spec.rb +131 -0
  40. data/spec/kd_expected_out.txt +10000 -0
  41. data/spec/kd_test_in.txt +10000 -0
  42. data/spec/kd_tree_spec.rb +34 -0
  43. data/spec/map_gc_mark_spec.rb +29 -0
  44. data/spec/priority_queue_spec.rb +75 -0
  45. data/spec/queue_spec.rb +61 -0
  46. data/spec/rb_tree_map_spec.rb +123 -0
  47. data/spec/search_spec.rb +28 -0
  48. data/spec/sort_spec.rb +29 -0
  49. data/spec/splay_tree_map_spec.rb +106 -0
  50. data/spec/stack_spec.rb +60 -0
  51. data/spec/string_spec.rb +15 -0
  52. data/spec/suffix_array_spec.rb +40 -0
  53. data/spec/trie_spec.rb +59 -0
  54. metadata +108 -0
@@ -0,0 +1,51 @@
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '../lib')
2
+ require 'algorithms'
3
+ include Containers
4
+
5
+ require 'rubygems'
6
+ require 'rbench'
7
+
8
+ RBench.run(2) do
9
+ trees = %w(hash rbtree splaytree)
10
+ trees.each { |tree| self.send(:column, tree.intern) }
11
+
12
+ rbtree = RBTreeMap.new
13
+ splaytree = SplayTreeMap.new
14
+ hash = Hash.new
15
+
16
+ random_array = Array.new(300000) { |i| rand(i) }
17
+
18
+ report "Insertion" do
19
+ rbtree { random_array.each_with_index { |x,index| rbtree[index] = x } }
20
+ splaytree { random_array.each_with_index { |x,index| splaytree[index] = x } }
21
+ hash { random_array.each_with_index { |x,index| hash[index] = x } }
22
+ end
23
+
24
+ report "has_key? (linear order)" do
25
+ rbtree { random_array.each { |n| rbtree.has_key?(n) } }
26
+ splaytree { random_array.each { |n| splaytree.has_key?(n) } }
27
+ hash { random_array.each { |n| hash.has_key?(n) } }
28
+ end
29
+
30
+ report "Lookup in sorted order" do
31
+ rbtree { rbtree.each { |k, v| k } }
32
+ splaytree { splaytree.each { |k, v| k } }
33
+ hash { hash.sort.each { |k, v| k } }
34
+
35
+ # a1, a2, a3 = [], [], []
36
+ # rbtree.each { |k, v| a1 << k }
37
+ # splaytree.each { |k, v| a2 << k }
38
+ # hash.sort.each { |k, v| a3 << k }
39
+ #
40
+ # puts "Lookup correct" if a1 == a2 && a1 == a3
41
+ end
42
+
43
+ report "Random lookups in a smaller subset" do
44
+ select_subset = random_array[0..random_array.size/20] # 5%
45
+ size = select_subset.size
46
+ rbtree { 10000.times { rbtree[ select_subset[rand(size)] ] } }
47
+ splaytree { 10000.times { splaytree[ select_subset[rand(size)] ] } }
48
+ hash { 10000.times { hash[ select_subset[rand(size)] ] } }
49
+ end
50
+
51
+ end
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = "CString"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -0,0 +1,68 @@
1
+ #include "ruby.h"
2
+
3
+ long min_three(long a, long b, long c) {
4
+ long min = a;
5
+ if (b < min)
6
+ min = b;
7
+ if( c < min)
8
+ min = c;
9
+ return min;
10
+ }
11
+
12
+ long levenshtein_distance(VALUE str1, VALUE str2) {
13
+ long i, j, s1_len, s2_len, *d;
14
+ char * s = RSTRING_PTR(str1);
15
+ char * t = RSTRING_PTR(str2);
16
+ s1_len = RSTRING_LEN(str1);
17
+ s2_len = RSTRING_LEN(str2);
18
+
19
+ if (s1_len == 0) {
20
+ return s2_len;
21
+ } else if (s2_len == 0) {
22
+ return s1_len;
23
+ }
24
+
25
+ // We need one extra col and row for the matrix for starting values
26
+ s1_len++;
27
+ s2_len++;
28
+
29
+ d = xmalloc(sizeof(typeof(d)) * s1_len * s2_len);
30
+
31
+ for (i = 0; i < s1_len; i++) {
32
+ d[i] = i; // d[i, 0] = i
33
+ }
34
+ for (j = 0; j < s2_len; j++) {
35
+ d[j*s1_len] = j; // d[0, j] = j
36
+ }
37
+
38
+ for (i = 1; i < s1_len; i++) {
39
+ for (j = 1; j < s2_len; j++) {
40
+ if (s[i-1] == t[j-1]) {
41
+ d[j * s1_len + i] = d[(j-1) * s1_len + (i-1)];
42
+ } else {
43
+ d[j * s1_len + i] = 1 + min_three(
44
+ d[j * s1_len + (i-1)],
45
+ d[(j-1) * s1_len + i],
46
+ d[(j-1) * s1_len + (i-1)]
47
+ );
48
+ }
49
+ }
50
+ }
51
+ i = d[s1_len * s2_len -1];
52
+ xfree(d);
53
+ return i;
54
+ }
55
+
56
+ static VALUE lev_dist(VALUE self, VALUE str1, VALUE str2) {
57
+ return LONG2FIX(levenshtein_distance( str1, str2 ));
58
+ }
59
+
60
+ static VALUE mAlgorithms;
61
+ static VALUE mString;
62
+
63
+ void Init_CString() {
64
+ mAlgorithms = rb_define_module("Algorithms");
65
+ mString = rb_define_module_under(mAlgorithms, "String");
66
+ rb_define_singleton_method(mString, "levenshtein_dist", lev_dist, 2);
67
+ }
68
+
@@ -0,0 +1,247 @@
1
+ #include "ruby.h"
2
+
3
+ typedef struct struct_bst_node {
4
+ VALUE key;
5
+ VALUE value;
6
+ struct struct_bst_node *left;
7
+ struct struct_bst_node *right;
8
+ struct struct_bst_node *parent;
9
+ } bst_node;
10
+
11
+ typedef struct struct_bst {
12
+ bst_node *root;
13
+ int (*compare_function)(VALUE key1, VALUE key2);
14
+ unsigned int size;
15
+ } bst;
16
+
17
+ static VALUE bst_initialize(VALUE self) {
18
+ return self;
19
+ }
20
+
21
+ static bst* get_bst_from_self(VALUE self) {
22
+ bst *tree;
23
+ Data_Get_Struct(self, bst, tree);
24
+ return tree;
25
+ }
26
+
27
+ static bst* bst_each_node(bst *tree, bst_node *node, void (*each)(bst *tree_, bst_node *node_, void* args), void* arguments) {
28
+ if (!node)
29
+ return NULL;
30
+
31
+ if (node->left)
32
+ bst_each_node(tree, node->left, each, arguments);
33
+
34
+ (*each)(tree, node, arguments);
35
+
36
+ if (node->right)
37
+ bst_each_node(tree, node->right, each, arguments);
38
+ return tree;
39
+ }
40
+
41
+ static bst* bst_each(bst *tree, void (*each)(bst *tree, bst_node *node, void *args), void* arguments) {
42
+ if (tree->root)
43
+ bst_each_node(tree, tree->root, each, arguments);
44
+ return tree;
45
+ }
46
+
47
+ static VALUE id_compare_operator;
48
+
49
+ static int bst_compare_function(VALUE a, VALUE b) {
50
+ if (a == b) return 0;
51
+ if (FIXNUM_P(a) && FIXNUM_P(b)) {
52
+ long x = FIX2LONG(a), y = FIX2LONG(b);
53
+ if (x == y) return 0;
54
+ if (x > y) return 1;
55
+ return -1;
56
+ }
57
+ if (TYPE(a) == T_STRING && rb_obj_is_kind_of(a, rb_cString) &&
58
+ TYPE(b) == T_STRING && rb_obj_is_kind_of(b, rb_cString)) {
59
+ return rb_str_cmp(a, b);
60
+ }
61
+ return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
62
+ }
63
+
64
+ static void insert_element(bst *tree, bst_node **t,bst_node *newElement) {
65
+ int cmp;
66
+ bst_node *y = NULL;
67
+ bst_node *x = *t;
68
+ while (x != NULL) {
69
+ y = x;
70
+ cmp = tree->compare_function(newElement->key, x->key);
71
+ if (cmp < 0) x = x->left;
72
+ else x = x->right;
73
+ }
74
+ newElement->parent = y;
75
+ if (y == NULL) *t = newElement;
76
+ else {
77
+ cmp = tree->compare_function(newElement->key, y->key);
78
+ if (cmp < 0)
79
+ y->left = newElement;
80
+ else
81
+ y->right = newElement;
82
+ }
83
+ }
84
+
85
+
86
+ static bst_node* create_node(VALUE key_value,VALUE value) {
87
+ bst_node *new_node = ALLOC(bst_node);
88
+ new_node->value = value;
89
+ new_node->key = key_value;
90
+ new_node->left = NULL;
91
+ new_node->right = NULL;
92
+ new_node->parent = NULL;
93
+ return new_node;
94
+ }
95
+
96
+ static bst_node* tree_minimum (bst_node *tree) {
97
+ bst_node *x = tree;
98
+ while (x->left) x = x->left;
99
+ return x;
100
+ }
101
+
102
+ static bst_node* tree_maximum (bst_node *tree) {
103
+ bst_node *x = tree;
104
+ while (x->right) x = x->right;
105
+ return x;
106
+ }
107
+
108
+ static bst_node* node_successor (bst_node *tree,bst_node *x) {
109
+ if (x->right) return tree_minimum(x->right);
110
+ bst_node *y = x->parent;
111
+ while (y && x == y->right) {
112
+ x = y;
113
+ y = x->parent;
114
+ }
115
+ return y;
116
+ }
117
+
118
+
119
+ static bst_node* delete_node (bst_node **tree,bst_node *tobeDeleted) {
120
+ bst_node *y,*x;
121
+
122
+ if ((tobeDeleted->left == NULL) || (tobeDeleted->right == NULL)) y = tobeDeleted;
123
+ else y = node_successor(*tree,tobeDeleted);
124
+
125
+ if (y->left) x = y->left;
126
+ else x = y->right;
127
+
128
+ if (x) x->parent = y->parent;
129
+
130
+ if (y->parent == NULL) {
131
+ *tree = x;
132
+ return y;
133
+ } else if (y == y->parent->left) {
134
+ y->parent->left = x;
135
+ } else {
136
+ y->parent->right = x;
137
+ }
138
+
139
+ if (tobeDeleted != y) tobeDeleted->key = y->key;
140
+ return y;
141
+ }
142
+
143
+ static bst_node* search_node(bst *tree, bst_node *node, VALUE key) {
144
+ bst_node *x = node;
145
+ int cmp;
146
+
147
+ while(x) {
148
+ cmp = tree->compare_function(key, x->key);
149
+ if (cmp == 0) return x;
150
+ else if (cmp < 0) { x = x->left; }
151
+ else { x = x->right; }
152
+ }
153
+ return NULL;
154
+ }
155
+
156
+ static void recursively_mark_nodes(bst_node *node) {
157
+ if(node) {
158
+ rb_gc_mark(node->key);
159
+ rb_gc_mark(node->value);
160
+ recursively_mark_nodes(node->left);
161
+ recursively_mark_nodes(node->right);
162
+ }
163
+ }
164
+
165
+ static void bst_mark(bst *tree) {
166
+ if (tree) {
167
+ recursively_mark_nodes(tree->root);
168
+ }
169
+ }
170
+
171
+ static void recursively_free_nodes(bst_node *node) {
172
+ if(node) {
173
+ recursively_free_nodes(node->left);
174
+ recursively_free_nodes(node->right);
175
+ xfree(node);
176
+ }
177
+ }
178
+
179
+ static void bst_free(bst *tree) {
180
+ if (tree) {
181
+ recursively_free_nodes(tree->root);
182
+ }
183
+ }
184
+
185
+ static bst* create_bst(int (*compare_function)(VALUE, VALUE)) {
186
+ bst *tree = ALLOC(bst);
187
+ tree->compare_function = compare_function;
188
+ tree->root = NULL;
189
+ tree->size = 0;
190
+ return tree;
191
+ }
192
+
193
+ static VALUE bst_alloc(VALUE klass) {
194
+ bst *tree = create_bst(&bst_compare_function);
195
+ return Data_Wrap_Struct(klass, bst_mark, bst_free, tree);
196
+ }
197
+
198
+ static VALUE rb_bst_push_value(VALUE self, VALUE key, VALUE value) {
199
+ bst *tree = get_bst_from_self(self);
200
+ insert_element(tree, &(tree->root), create_node(key,value));
201
+ tree->size++;
202
+ return self;
203
+ }
204
+
205
+ static void bst_each_helper(bst *tree, bst_node *node, void *args) {
206
+ rb_yield(rb_ary_new3(2, node->key, node->value));
207
+ };
208
+
209
+ static VALUE rb_bst_each(VALUE self) {
210
+ bst *tree = get_bst_from_self(self);
211
+ bst_each(tree, &bst_each_helper, NULL);
212
+ return self;
213
+ }
214
+
215
+ static VALUE rb_bst_delete(VALUE self, VALUE key) {
216
+ bst *tree = get_bst_from_self(self);
217
+ bst_node *tobeDeleted = search_node(tree, tree->root, key);
218
+ if(tobeDeleted) {
219
+ tree->size -= 1;
220
+ bst_node *deletedNode = delete_node(&(tree->root),tobeDeleted);
221
+ return deletedNode->value;
222
+ }
223
+ return Qnil;
224
+ }
225
+
226
+ static VALUE rb_bst_size(VALUE self) {
227
+ bst *tree;
228
+ Data_Get_Struct(self,bst,tree);
229
+ return INT2FIX(tree->size);
230
+ }
231
+
232
+ static VALUE CBst;
233
+ static VALUE mContainers;
234
+
235
+ void Init_CBst() {
236
+ id_compare_operator = rb_intern("<=>");
237
+
238
+ mContainers = rb_define_module("Containers");
239
+ CBst = rb_define_class_under(mContainers, "CBst", rb_cObject);
240
+ rb_define_alloc_func(CBst, bst_alloc);
241
+ rb_define_method(CBst, "initialize", bst_initialize, 0);
242
+ rb_define_method(CBst, "push", rb_bst_push_value, 2);
243
+ rb_define_alias(CBst, "[]=", "push");
244
+ rb_define_method(CBst, "each", rb_bst_each, 0);
245
+ rb_define_method(CBst, "delete", rb_bst_delete, 1);
246
+ rb_define_method(CBst, "size", rb_bst_size, 0);
247
+ }
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = "CBst"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -0,0 +1,247 @@
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
+ xfree(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_mark(void *ptr) {
60
+ if (ptr) {
61
+ deque *deque = ptr;
62
+ deque_node *node = deque->front;
63
+ while(node) {
64
+ rb_gc_mark(node->obj);
65
+ node = node->right;
66
+ }
67
+ }
68
+ }
69
+
70
+ static void deque_free(void *ptr) {
71
+ if (ptr) {
72
+ deque *deque = ptr;
73
+ free_nodes(deque->front);
74
+ xfree(deque);
75
+ }
76
+ }
77
+
78
+ static VALUE deque_alloc(VALUE klass) {
79
+ deque *deque = create_deque();
80
+ return Data_Wrap_Struct(klass, deque_mark, deque_free, deque);
81
+ }
82
+
83
+ static VALUE deque_push_front(VALUE self, VALUE obj) {
84
+ deque *deque = get_deque_from_self(self);
85
+ deque_node *node = create_node(obj);
86
+ if(deque->front) {
87
+ node->right = deque->front;
88
+ deque->front->left = node;
89
+ deque->front = node;
90
+ }
91
+ else {
92
+ deque->front = node;
93
+ deque->back = node;
94
+ }
95
+ deque->size++;
96
+ return obj;
97
+ }
98
+
99
+ static VALUE deque_push_back(VALUE self, VALUE obj) {
100
+ deque *deque = get_deque_from_self(self);
101
+ deque_node *node = create_node(obj);
102
+ if(deque->back) {
103
+ node->left = deque->back;
104
+ deque->back->right = node;
105
+ deque->back = node;
106
+ }
107
+ else {
108
+ deque->front = node;
109
+ deque->back = node;
110
+ }
111
+ deque->size++;
112
+ return obj;
113
+ }
114
+
115
+ static VALUE deque_pop_front(VALUE self) {
116
+ deque *deque = get_deque_from_self(self);
117
+ VALUE obj;
118
+ if(!deque->front)
119
+ return Qnil;
120
+ deque_node *node = deque->front;
121
+ obj = node->obj;
122
+ if(deque->size == 1) {
123
+ clear_deque(deque);
124
+ return obj;
125
+ }
126
+ deque->front->right->left = NULL;
127
+ deque->front = deque->front->right;
128
+ deque->size--;
129
+ return obj;
130
+ }
131
+
132
+ static VALUE deque_front(VALUE self) {
133
+ deque *deque = get_deque_from_self(self);
134
+ if(deque->front)
135
+ return deque->front->obj;
136
+
137
+ return Qnil;
138
+ }
139
+
140
+ static VALUE deque_back(VALUE self) {
141
+ deque *deque = get_deque_from_self(self);
142
+ if(deque->back)
143
+ return deque->back->obj;
144
+
145
+ return Qnil;
146
+ }
147
+
148
+ static VALUE deque_pop_back(VALUE self) {
149
+ deque *deque = get_deque_from_self(self);
150
+ VALUE obj;
151
+ if(!deque->back)
152
+ return Qnil;
153
+ deque_node *node = deque->back;
154
+ obj = node->obj;
155
+ if(deque->size == 1) {
156
+ clear_deque(deque);
157
+ return obj;
158
+ }
159
+ deque->back->left->right = NULL;
160
+ deque->back = deque->back->left;
161
+ deque->size--;
162
+ return obj;
163
+ }
164
+
165
+ static VALUE deque_clear(VALUE self) {
166
+ deque *deque = get_deque_from_self(self);
167
+ clear_deque(deque);
168
+ return Qnil;
169
+ }
170
+
171
+ static VALUE deque_size(VALUE self) {
172
+ deque *deque = get_deque_from_self(self);
173
+ return INT2NUM(deque->size);
174
+ }
175
+
176
+ static VALUE deque_is_empty(VALUE self) {
177
+ deque *deque = get_deque_from_self(self);
178
+ return (deque->size == 0) ? Qtrue : Qfalse;
179
+ }
180
+
181
+ static VALUE deque_each_forward(VALUE self) {
182
+ deque *deque = get_deque_from_self(self);
183
+ deque_node *node = deque->front;
184
+ while(node) {
185
+ rb_yield(node->obj);
186
+ node = node->right;
187
+ }
188
+ return self;
189
+ }
190
+
191
+ static VALUE deque_each_backward(VALUE self) {
192
+ deque *deque = get_deque_from_self(self);
193
+ deque_node *node = deque->back;
194
+ while(node) {
195
+ rb_yield(node->obj);
196
+ node = node->left;
197
+ }
198
+ return self;
199
+ }
200
+
201
+ static VALUE deque_init(int argc, VALUE *argv, VALUE self)
202
+ {
203
+ long len, i;
204
+ VALUE ary;
205
+
206
+ if(argc == 0) {
207
+ return self;
208
+ }
209
+ else if(argc > 1) {
210
+ rb_raise(rb_eArgError, "wrong number of arguments");
211
+ }
212
+ else {
213
+ ary = rb_check_array_type(argv[0]);
214
+ if(!NIL_P(ary)) {
215
+ len = RARRAY_LEN(ary);
216
+ for (i = 0; i < len; i++) {
217
+ deque_push_back(self, RARRAY_PTR(ary)[i]);
218
+ }
219
+ }
220
+ }
221
+ return self;
222
+ }
223
+
224
+ static VALUE cDeque;
225
+ static VALUE mContainers;
226
+
227
+ void Init_CDeque() {
228
+ mContainers = rb_define_module("Containers");
229
+ cDeque = rb_define_class_under(mContainers, "CDeque", rb_cObject);
230
+ rb_define_alloc_func(cDeque, deque_alloc);
231
+ rb_define_method(cDeque, "initialize", deque_init, -1);
232
+ rb_define_method(cDeque, "push_front", deque_push_front, 1);
233
+ rb_define_method(cDeque, "push_back", deque_push_back, 1);
234
+ rb_define_method(cDeque, "clear", deque_clear, 0);
235
+ rb_define_method(cDeque, "front", deque_front, 0);
236
+ rb_define_method(cDeque, "back", deque_back, 0);
237
+ rb_define_method(cDeque, "pop_front", deque_pop_front, 0);
238
+ rb_define_method(cDeque, "pop_back", deque_pop_back, 0);
239
+ rb_define_method(cDeque, "size", deque_size, 0);
240
+ rb_define_alias(cDeque, "length", "size");
241
+ rb_define_method(cDeque, "empty?", deque_is_empty, 0);
242
+ rb_define_method(cDeque, "each_forward", deque_each_forward, 0);
243
+ rb_define_method(cDeque, "each_backward", deque_each_backward, 0);
244
+ rb_define_alias(cDeque, "each", "each_forward");
245
+ rb_define_alias(cDeque, "reverse_each", "each_backward");
246
+ rb_include_module(cDeque, rb_eval_string("Enumerable"));
247
+ }