algorithms 0.3.0 → 0.4.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.
- data/{History.txt → CHANGELOG.markdown} +11 -0
- data/Manifest +9 -1
- data/Rakefile +5 -23
- data/algorithms.gemspec +20 -16
- data/ext/algorithms/string/extconf.rb +4 -0
- data/ext/algorithms/string/string.c +68 -0
- data/ext/containers/bst/bst.c +247 -0
- data/ext/containers/bst/extconf.rb +4 -0
- data/lib/algorithms.rb +3 -6
- data/lib/algorithms/string.rb +8 -0
- data/lib/containers/heap.rb +16 -0
- data/spec/bst_gc_mark_spec.rb +25 -0
- data/spec/bst_spec.rb +25 -0
- data/spec/deque_spec.rb +2 -2
- data/spec/heap_spec.rb +5 -0
- data/spec/rb_tree_map_spec.rb +2 -2
- data/spec/splay_tree_map_spec.rb +2 -2
- data/spec/string_spec.rb +13 -0
- metadata +69 -36
@@ -1,3 +1,14 @@
|
|
1
|
+
=== April 19, 2012
|
2
|
+
|
3
|
+
* Pulled in fix for ruby 1.9 compilation error (sorry!!)
|
4
|
+
* Fix specs that broke with new rspec
|
5
|
+
* Migration to rubygems.org
|
6
|
+
* 0.4.0 release
|
7
|
+
|
8
|
+
=== Jan 3, 2009
|
9
|
+
|
10
|
+
* Levenshtein distance in C
|
11
|
+
|
1
12
|
=== April 3, 2009
|
2
13
|
|
3
14
|
* Finished C refactorization of SplayTree
|
data/Manifest
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
CHANGELOG.markdown
|
2
2
|
Manifest
|
3
3
|
README.markdown
|
4
4
|
Rakefile
|
@@ -6,6 +6,10 @@ algorithms.gemspec
|
|
6
6
|
benchmarks/deque.rb
|
7
7
|
benchmarks/sorts.rb
|
8
8
|
benchmarks/treemaps.rb
|
9
|
+
ext/algorithms/string/extconf.rb
|
10
|
+
ext/algorithms/string/string.c
|
11
|
+
ext/containers/bst/bst.c
|
12
|
+
ext/containers/bst/extconf.rb
|
9
13
|
ext/containers/deque/deque.c
|
10
14
|
ext/containers/deque/extconf.rb
|
11
15
|
ext/containers/rbtree_map/extconf.rb
|
@@ -15,6 +19,7 @@ ext/containers/splaytree_map/splaytree.c
|
|
15
19
|
lib/algorithms.rb
|
16
20
|
lib/algorithms/search.rb
|
17
21
|
lib/algorithms/sort.rb
|
22
|
+
lib/algorithms/string.rb
|
18
23
|
lib/containers/deque.rb
|
19
24
|
lib/containers/heap.rb
|
20
25
|
lib/containers/kd_tree.rb
|
@@ -25,6 +30,8 @@ lib/containers/splay_tree_map.rb
|
|
25
30
|
lib/containers/stack.rb
|
26
31
|
lib/containers/suffix_array.rb
|
27
32
|
lib/containers/trie.rb
|
33
|
+
spec/bst_gc_mark_spec.rb
|
34
|
+
spec/bst_spec.rb
|
28
35
|
spec/deque_gc_mark_spec.rb
|
29
36
|
spec/deque_spec.rb
|
30
37
|
spec/heap_spec.rb
|
@@ -39,5 +46,6 @@ spec/search_spec.rb
|
|
39
46
|
spec/sort_spec.rb
|
40
47
|
spec/splay_tree_map_spec.rb
|
41
48
|
spec/stack_spec.rb
|
49
|
+
spec/string_spec.rb
|
42
50
|
spec/suffix_array_spec.rb
|
43
51
|
spec/trie_spec.rb
|
data/Rakefile
CHANGED
@@ -4,28 +4,10 @@ require 'echoe'
|
|
4
4
|
Echoe.new('algorithms') do |p|
|
5
5
|
p.author = 'Kanwei Li'
|
6
6
|
p.email = 'kanwei@gmail.com'
|
7
|
-
p.summary = 'A library of algorithms and containers.'
|
8
|
-
p.url = '
|
9
|
-
p.version = "0.
|
7
|
+
p.summary = 'A library of algorithms and data structures (containers).'
|
8
|
+
p.url = 'https://rubygems.org/gems/algorithms'
|
9
|
+
p.version = "0.4.0"
|
10
|
+
p.retain_gemspec = true
|
10
11
|
p.runtime_dependencies = []
|
12
|
+
p.development_dependencies = ["rspec", "echoe"]
|
11
13
|
end
|
12
|
-
|
13
|
-
task :default => :spec
|
14
|
-
|
15
|
-
task :spec do
|
16
|
-
sh "spec spec/*.rb --color"
|
17
|
-
end
|
18
|
-
|
19
|
-
task :push do
|
20
|
-
sh "git push" # Rubyforge
|
21
|
-
sh "git push --tags" # Rubyforge
|
22
|
-
sh "git push gh" # Github
|
23
|
-
sh "git push gh --tags" # Github
|
24
|
-
end
|
25
|
-
|
26
|
-
task :hanna do
|
27
|
-
sh "rm -fr doc"
|
28
|
-
sh "hanna -SN lib/ -m Algorithms"
|
29
|
-
sh "scp -rq doc/* kanwei@rubyforge.org:/var/www/gforge-projects/algorithms"
|
30
|
-
end
|
31
|
-
|
data/algorithms.gemspec
CHANGED
@@ -1,32 +1,36 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
|
-
s.name =
|
5
|
-
s.version = "0.
|
4
|
+
s.name = "algorithms"
|
5
|
+
s.version = "0.4.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Kanwei Li"]
|
9
|
-
s.date =
|
10
|
-
s.description =
|
11
|
-
s.email =
|
12
|
-
s.extensions = ["ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/splaytree_map/extconf.rb"]
|
13
|
-
s.extra_rdoc_files = ["README.markdown", "ext/containers/deque/deque.c", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/rbtree_map/rbtree.c", "ext/containers/splaytree_map/extconf.rb", "ext/containers/splaytree_map/splaytree.c", "lib/algorithms.rb", "lib/algorithms/search.rb", "lib/algorithms/sort.rb", "lib/containers/deque.rb", "lib/containers/heap.rb", "lib/containers/kd_tree.rb", "lib/containers/priority_queue.rb", "lib/containers/queue.rb", "lib/containers/rb_tree_map.rb", "lib/containers/splay_tree_map.rb", "lib/containers/stack.rb", "lib/containers/suffix_array.rb", "lib/containers/trie.rb"]
|
14
|
-
s.files = ["
|
15
|
-
s.
|
16
|
-
s.homepage = %q{http://rubyforge.org/projects/algorithms/}
|
9
|
+
s.date = "2012-04-19"
|
10
|
+
s.description = "A library of algorithms and data structures (containers)."
|
11
|
+
s.email = "kanwei@gmail.com"
|
12
|
+
s.extensions = ["ext/algorithms/string/extconf.rb", "ext/containers/bst/extconf.rb", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/splaytree_map/extconf.rb"]
|
13
|
+
s.extra_rdoc_files = ["CHANGELOG.markdown", "README.markdown", "ext/algorithms/string/extconf.rb", "ext/algorithms/string/string.c", "ext/containers/bst/bst.c", "ext/containers/bst/extconf.rb", "ext/containers/deque/deque.c", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/rbtree_map/rbtree.c", "ext/containers/splaytree_map/extconf.rb", "ext/containers/splaytree_map/splaytree.c", "lib/algorithms.rb", "lib/algorithms/search.rb", "lib/algorithms/sort.rb", "lib/algorithms/string.rb", "lib/containers/deque.rb", "lib/containers/heap.rb", "lib/containers/kd_tree.rb", "lib/containers/priority_queue.rb", "lib/containers/queue.rb", "lib/containers/rb_tree_map.rb", "lib/containers/splay_tree_map.rb", "lib/containers/stack.rb", "lib/containers/suffix_array.rb", "lib/containers/trie.rb"]
|
14
|
+
s.files = ["CHANGELOG.markdown", "Manifest", "README.markdown", "Rakefile", "algorithms.gemspec", "benchmarks/deque.rb", "benchmarks/sorts.rb", "benchmarks/treemaps.rb", "ext/algorithms/string/extconf.rb", "ext/algorithms/string/string.c", "ext/containers/bst/bst.c", "ext/containers/bst/extconf.rb", "ext/containers/deque/deque.c", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/rbtree_map/rbtree.c", "ext/containers/splaytree_map/extconf.rb", "ext/containers/splaytree_map/splaytree.c", "lib/algorithms.rb", "lib/algorithms/search.rb", "lib/algorithms/sort.rb", "lib/algorithms/string.rb", "lib/containers/deque.rb", "lib/containers/heap.rb", "lib/containers/kd_tree.rb", "lib/containers/priority_queue.rb", "lib/containers/queue.rb", "lib/containers/rb_tree_map.rb", "lib/containers/splay_tree_map.rb", "lib/containers/stack.rb", "lib/containers/suffix_array.rb", "lib/containers/trie.rb", "spec/bst_gc_mark_spec.rb", "spec/bst_spec.rb", "spec/deque_gc_mark_spec.rb", "spec/deque_spec.rb", "spec/heap_spec.rb", "spec/kd_expected_out.txt", "spec/kd_test_in.txt", "spec/kd_tree_spec.rb", "spec/map_gc_mark_spec.rb", "spec/priority_queue_spec.rb", "spec/queue_spec.rb", "spec/rb_tree_map_spec.rb", "spec/search_spec.rb", "spec/sort_spec.rb", "spec/splay_tree_map_spec.rb", "spec/stack_spec.rb", "spec/string_spec.rb", "spec/suffix_array_spec.rb", "spec/trie_spec.rb"]
|
15
|
+
s.homepage = "https://rubygems.org/gems/algorithms"
|
17
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Algorithms", "--main", "README.markdown"]
|
18
17
|
s.require_paths = ["lib", "ext"]
|
19
|
-
s.rubyforge_project =
|
20
|
-
s.rubygems_version =
|
21
|
-
s.summary =
|
18
|
+
s.rubyforge_project = "algorithms"
|
19
|
+
s.rubygems_version = "1.8.15"
|
20
|
+
s.summary = "A library of algorithms and data structures (containers)."
|
22
21
|
|
23
22
|
if s.respond_to? :specification_version then
|
24
|
-
|
25
|
-
s.specification_version = 2
|
23
|
+
s.specification_version = 3
|
26
24
|
|
27
|
-
if Gem::Version.new(Gem::
|
25
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
26
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
27
|
+
s.add_development_dependency(%q<echoe>, [">= 0"])
|
28
28
|
else
|
29
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
30
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
29
31
|
end
|
30
32
|
else
|
33
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
34
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
31
35
|
end
|
32
36
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
int min(int a, int b, int c) {
|
4
|
+
int min = a;
|
5
|
+
if (b < min)
|
6
|
+
min = b;
|
7
|
+
if( c < min)
|
8
|
+
min = c;
|
9
|
+
return min;
|
10
|
+
}
|
11
|
+
|
12
|
+
int levenshtein_distance(VALUE str1, VALUE str2) {
|
13
|
+
int 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 = malloc(sizeof(int) * (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] = min(
|
44
|
+
d[j * s1_len + (i-1)],
|
45
|
+
d[(j-1) * s1_len + i],
|
46
|
+
d[(j-1) * s1_len + (i-1)]
|
47
|
+
) + 1;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
i = d[s1_len * s2_len -1];
|
52
|
+
free(d);
|
53
|
+
return i;
|
54
|
+
}
|
55
|
+
|
56
|
+
static VALUE lev_dist(VALUE self, VALUE str1, VALUE str2) {
|
57
|
+
return INT2FIX(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 int 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
|
+
free(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
|
+
}
|
data/lib/algorithms.rb
CHANGED
@@ -43,19 +43,16 @@
|
|
43
43
|
- Shell sort - Algorithms::Sort.shell_sort
|
44
44
|
- Quicksort - Algorithms::Sort.quicksort
|
45
45
|
- Mergesort - Algorithms::Sort.mergesort
|
46
|
+
* String algorithms
|
47
|
+
- Levenshtein distance - Algorithms::String.levenshtein_dist
|
46
48
|
=end
|
47
49
|
|
48
50
|
module Algorithms; end
|
49
51
|
module Containers; end
|
50
52
|
|
51
|
-
begin
|
52
|
-
require 'CBst'
|
53
|
-
Containers::Bst = Containers::CBst
|
54
|
-
rescue LoadError # C Version could not be found
|
55
|
-
end
|
56
|
-
|
57
53
|
require 'algorithms/search'
|
58
54
|
require 'algorithms/sort'
|
55
|
+
require 'algorithms/string'
|
59
56
|
require 'containers/heap'
|
60
57
|
require 'containers/stack'
|
61
58
|
require 'containers/deque'
|
data/lib/containers/heap.rb
CHANGED
@@ -117,6 +117,22 @@ class Containers::Heap
|
|
117
117
|
@next && @next.value
|
118
118
|
end
|
119
119
|
|
120
|
+
# call-seq:
|
121
|
+
# next_key -> key
|
122
|
+
# next_key -> nil
|
123
|
+
#
|
124
|
+
# Returns the key associated with the next item in heap order, but does not remove the value.
|
125
|
+
#
|
126
|
+
# Complexity: O(1)
|
127
|
+
#
|
128
|
+
# minheap = MinHeap.new
|
129
|
+
# minheap.push(1, :a)
|
130
|
+
# minheap.next_key #=> 1
|
131
|
+
#
|
132
|
+
def next_key
|
133
|
+
@next && @next.key
|
134
|
+
end
|
135
|
+
|
120
136
|
# call-seq:
|
121
137
|
# clear -> nil
|
122
138
|
#
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
|
+
# require 'algorithms'
|
3
|
+
#
|
4
|
+
# if defined? Containers::CBst
|
5
|
+
# describe "CBst" do
|
6
|
+
# it "should mark ruby object references" do
|
7
|
+
# anon_key_class = Class.new do
|
8
|
+
# attr :value
|
9
|
+
# def initialize(x); @value = x; end
|
10
|
+
# def <=>(other); value <=> other.value; end
|
11
|
+
# end
|
12
|
+
# anon_val_class = Class.new
|
13
|
+
# @bst = Containers::CBst.new
|
14
|
+
# 100.times { |x| @bst.push(anon_key_class.new(x), anon_val_class.new) }
|
15
|
+
# # Mark and sweep
|
16
|
+
# ObjectSpace.garbage_collect
|
17
|
+
# # Check if any instances were swept
|
18
|
+
# count = 0
|
19
|
+
# ObjectSpace.each_object(anon_key_class) { |x| count += 1 }
|
20
|
+
# count.should eql(100)
|
21
|
+
# ObjectSpace.each_object(anon_val_class) { |x| count += 1 }
|
22
|
+
# count.should eql(200)
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# end
|
data/spec/bst_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
|
+
# require "algorithms"
|
3
|
+
#
|
4
|
+
# begin
|
5
|
+
# Containers::CBst
|
6
|
+
# describe "binary search tree" do
|
7
|
+
# it "should let user push new elements with key" do
|
8
|
+
# @bst = Containers::CBst.new
|
9
|
+
# 100.times { |x| @bst.push(x, "hello : #{x}") }
|
10
|
+
# @bst.size.should eql(100)
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# it "should allow users to delete elements" do
|
14
|
+
# @bst = Containers::CBst.new
|
15
|
+
# @bst.push(10, "hello world")
|
16
|
+
# @bst.push(11, "hello world")
|
17
|
+
# @bst.delete(11)
|
18
|
+
# @bst.size.should eql(1)
|
19
|
+
# @bst.delete(10)
|
20
|
+
# @bst.size.should eql(0)
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# end
|
24
|
+
# rescue Exception
|
25
|
+
# end
|
data/spec/deque_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
2
|
require 'algorithms'
|
3
3
|
|
4
|
-
|
4
|
+
shared_examples "(empty deque)" do
|
5
5
|
it "should return nil when popping objects" do
|
6
6
|
@deque.pop_front.should be_nil
|
7
7
|
@deque.pop_back.should be_nil
|
@@ -31,7 +31,7 @@ describe "(empty deque)", :shared => true do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
|
34
|
+
shared_examples "(non-empty deque)" do
|
35
35
|
before(:each) do
|
36
36
|
@deque.push_back(10)
|
37
37
|
@deque.push_back("10")
|
data/spec/heap_spec.rb
CHANGED
@@ -46,6 +46,11 @@ describe Containers::Heap do
|
|
46
46
|
@heap.size.should eql(@num_items)
|
47
47
|
end
|
48
48
|
|
49
|
+
it "should have a next value" do
|
50
|
+
@heap.next.should be_true
|
51
|
+
@heap.next_key.should be_true
|
52
|
+
end
|
53
|
+
|
49
54
|
it "should delete random keys" do
|
50
55
|
@heap.delete(@random_array[0]).should eql(@random_array[0])
|
51
56
|
@heap.delete(@random_array[1]).should eql(@random_array[1])
|
data/spec/rb_tree_map_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
2
|
require 'algorithms'
|
3
3
|
|
4
|
-
|
4
|
+
shared_examples "empty rbtree" do
|
5
5
|
it "should let you push stuff in" do
|
6
6
|
100.times { |x| @tree[x] = x }
|
7
7
|
@tree.size.should eql(100)
|
@@ -31,7 +31,7 @@ describe "empty rbtree", :shared => true do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
|
34
|
+
shared_examples "non-empty rbtree" do
|
35
35
|
before(:each) do
|
36
36
|
@num_items = 1000
|
37
37
|
@random_array = Array.new(@num_items) { rand(@num_items) }
|
data/spec/splay_tree_map_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
2
|
require 'algorithms'
|
3
3
|
|
4
|
-
|
4
|
+
shared_examples "empty splaytree" do
|
5
5
|
it "should let you push stuff in" do
|
6
6
|
100.times { |x| @tree[x] = x }
|
7
7
|
@tree.size.should eql(100)
|
@@ -25,7 +25,7 @@ describe "empty splaytree", :shared => true do
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
shared_examples "non-empty splaytree" do
|
29
29
|
before(:each) do
|
30
30
|
@num_items = 100
|
31
31
|
@random_array = []
|
data/spec/string_spec.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
|
+
require 'algorithms'
|
3
|
+
|
4
|
+
describe "string algorithms" do
|
5
|
+
it "should do levenshtein distance" do
|
6
|
+
Algorithms::String.levenshtein_dist("Hello", "Hel").should eql(2)
|
7
|
+
Algorithms::String.levenshtein_dist("Hello", "").should eql(5)
|
8
|
+
Algorithms::String.levenshtein_dist("", "Hello").should eql(5)
|
9
|
+
Algorithms::String.levenshtein_dist("Hello", "Hello").should eql(0)
|
10
|
+
Algorithms::String.levenshtein_dist("Hello", "ello").should eql(1)
|
11
|
+
Algorithms::String.levenshtein_dist("Hello", "Mello").should eql(1)
|
12
|
+
end
|
13
|
+
end
|
metadata
CHANGED
@@ -1,28 +1,54 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: algorithms
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
+
authors:
|
7
8
|
- Kanwei Li
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
date: 2012-04-19 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70335276597400 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70335276597400
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: echoe
|
27
|
+
requirement: &70335276596820 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70335276596820
|
36
|
+
description: A library of algorithms and data structures (containers).
|
17
37
|
email: kanwei@gmail.com
|
18
38
|
executables: []
|
19
|
-
|
20
|
-
|
39
|
+
extensions:
|
40
|
+
- ext/algorithms/string/extconf.rb
|
41
|
+
- ext/containers/bst/extconf.rb
|
21
42
|
- ext/containers/deque/extconf.rb
|
22
43
|
- ext/containers/rbtree_map/extconf.rb
|
23
44
|
- ext/containers/splaytree_map/extconf.rb
|
24
|
-
extra_rdoc_files:
|
45
|
+
extra_rdoc_files:
|
46
|
+
- CHANGELOG.markdown
|
25
47
|
- README.markdown
|
48
|
+
- ext/algorithms/string/extconf.rb
|
49
|
+
- ext/algorithms/string/string.c
|
50
|
+
- ext/containers/bst/bst.c
|
51
|
+
- ext/containers/bst/extconf.rb
|
26
52
|
- ext/containers/deque/deque.c
|
27
53
|
- ext/containers/deque/extconf.rb
|
28
54
|
- ext/containers/rbtree_map/extconf.rb
|
@@ -32,6 +58,7 @@ extra_rdoc_files:
|
|
32
58
|
- lib/algorithms.rb
|
33
59
|
- lib/algorithms/search.rb
|
34
60
|
- lib/algorithms/sort.rb
|
61
|
+
- lib/algorithms/string.rb
|
35
62
|
- lib/containers/deque.rb
|
36
63
|
- lib/containers/heap.rb
|
37
64
|
- lib/containers/kd_tree.rb
|
@@ -42,8 +69,8 @@ extra_rdoc_files:
|
|
42
69
|
- lib/containers/stack.rb
|
43
70
|
- lib/containers/suffix_array.rb
|
44
71
|
- lib/containers/trie.rb
|
45
|
-
files:
|
46
|
-
-
|
72
|
+
files:
|
73
|
+
- CHANGELOG.markdown
|
47
74
|
- Manifest
|
48
75
|
- README.markdown
|
49
76
|
- Rakefile
|
@@ -51,6 +78,10 @@ files:
|
|
51
78
|
- benchmarks/deque.rb
|
52
79
|
- benchmarks/sorts.rb
|
53
80
|
- benchmarks/treemaps.rb
|
81
|
+
- ext/algorithms/string/extconf.rb
|
82
|
+
- ext/algorithms/string/string.c
|
83
|
+
- ext/containers/bst/bst.c
|
84
|
+
- ext/containers/bst/extconf.rb
|
54
85
|
- ext/containers/deque/deque.c
|
55
86
|
- ext/containers/deque/extconf.rb
|
56
87
|
- ext/containers/rbtree_map/extconf.rb
|
@@ -60,6 +91,7 @@ files:
|
|
60
91
|
- lib/algorithms.rb
|
61
92
|
- lib/algorithms/search.rb
|
62
93
|
- lib/algorithms/sort.rb
|
94
|
+
- lib/algorithms/string.rb
|
63
95
|
- lib/containers/deque.rb
|
64
96
|
- lib/containers/heap.rb
|
65
97
|
- lib/containers/kd_tree.rb
|
@@ -70,6 +102,8 @@ files:
|
|
70
102
|
- lib/containers/stack.rb
|
71
103
|
- lib/containers/suffix_array.rb
|
72
104
|
- lib/containers/trie.rb
|
105
|
+
- spec/bst_gc_mark_spec.rb
|
106
|
+
- spec/bst_spec.rb
|
73
107
|
- spec/deque_gc_mark_spec.rb
|
74
108
|
- spec/deque_spec.rb
|
75
109
|
- spec/heap_spec.rb
|
@@ -84,39 +118,38 @@ files:
|
|
84
118
|
- spec/sort_spec.rb
|
85
119
|
- spec/splay_tree_map_spec.rb
|
86
120
|
- spec/stack_spec.rb
|
121
|
+
- spec/string_spec.rb
|
87
122
|
- spec/suffix_array_spec.rb
|
88
123
|
- spec/trie_spec.rb
|
89
|
-
|
90
|
-
|
124
|
+
homepage: https://rubygems.org/gems/algorithms
|
125
|
+
licenses: []
|
91
126
|
post_install_message:
|
92
|
-
rdoc_options:
|
127
|
+
rdoc_options:
|
93
128
|
- --line-numbers
|
94
129
|
- --inline-source
|
95
130
|
- --title
|
96
131
|
- Algorithms
|
97
132
|
- --main
|
98
133
|
- README.markdown
|
99
|
-
require_paths:
|
134
|
+
require_paths:
|
100
135
|
- lib
|
101
136
|
- ext
|
102
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
145
|
+
requirements:
|
146
|
+
- - ! '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '1.2'
|
114
149
|
requirements: []
|
115
|
-
|
116
150
|
rubyforge_project: algorithms
|
117
|
-
rubygems_version: 1.
|
151
|
+
rubygems_version: 1.8.15
|
118
152
|
signing_key:
|
119
|
-
specification_version:
|
120
|
-
summary: A library of algorithms and containers.
|
153
|
+
specification_version: 3
|
154
|
+
summary: A library of algorithms and data structures (containers).
|
121
155
|
test_files: []
|
122
|
-
|