tyler-trie 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.yml +1 -1
- data/ext/trie/trie.c +60 -4
- data/spec/trie_spec.rb +23 -0
- metadata +1 -1
data/VERSION.yml
CHANGED
data/ext/trie/trie.c
CHANGED
@@ -83,13 +83,21 @@ static VALUE trie_get(VALUE self, VALUE key) {
|
|
83
83
|
return Qnil;
|
84
84
|
}
|
85
85
|
|
86
|
-
static VALUE trie_add(VALUE self, VALUE
|
86
|
+
static VALUE trie_add(VALUE self, VALUE args) {
|
87
87
|
SBTrie *sb_trie;
|
88
88
|
Data_Get_Struct(self, SBTrie, sb_trie);
|
89
89
|
|
90
|
+
long size = RARRAY(args)->len;
|
91
|
+
if(size < 1 || size > 2)
|
92
|
+
return Qnil;
|
93
|
+
|
94
|
+
VALUE key;
|
95
|
+
key = RARRAY(args)->ptr[0];
|
96
|
+
short value = size == 2 ? NUM2INT(RARRAY(args)->ptr[1]) : TRIE_DATA_ERROR;
|
97
|
+
|
90
98
|
const TrieChar *sb_key = stringToTrieChar(key);
|
91
99
|
|
92
|
-
if(sb_trie_store(sb_trie, sb_key,
|
100
|
+
if(sb_trie_store(sb_trie, sb_key, value))
|
93
101
|
return Qtrue;
|
94
102
|
else
|
95
103
|
return Qnil;
|
@@ -114,7 +122,7 @@ static VALUE walk_all_paths(VALUE children, SBTrieState *state, char *prefix) {
|
|
114
122
|
SBTrieState *next_state = sb_trie_state_clone(state);
|
115
123
|
sb_trie_state_walk(next_state, (TrieChar)c);
|
116
124
|
|
117
|
-
char *word = (char*)
|
125
|
+
char *word = (char*)malloc(strlen(prefix) + 2);
|
118
126
|
strcat(strcpy(word, prefix), (char*)&c);
|
119
127
|
|
120
128
|
if(sb_trie_state_is_terminal(next_state))
|
@@ -154,6 +162,53 @@ static VALUE trie_children(VALUE self, VALUE prefix) {
|
|
154
162
|
return children;
|
155
163
|
}
|
156
164
|
|
165
|
+
static VALUE trie_walk_to_terminal(VALUE self, VALUE args) {
|
166
|
+
SBTrie *sb_trie;
|
167
|
+
Data_Get_Struct(self, SBTrie, sb_trie);
|
168
|
+
|
169
|
+
long size = RARRAY(args)->len;
|
170
|
+
if(size < 1 || size > 2)
|
171
|
+
return Qnil;
|
172
|
+
|
173
|
+
VALUE rb_path;
|
174
|
+
rb_path = RARRAY(args)->ptr[0];
|
175
|
+
short include_value = size == 2 ? RTEST(RARRAY(args)->ptr[1]) : 0;
|
176
|
+
|
177
|
+
SBTrieState *state = sb_trie_root(sb_trie);
|
178
|
+
|
179
|
+
char *path = RSTRING(rb_path)->ptr;
|
180
|
+
|
181
|
+
TrieChar *iterator = (TrieChar*)path;
|
182
|
+
while(*iterator != '\0') {
|
183
|
+
if(sb_trie_state_is_terminal(state)) {
|
184
|
+
int word_length = (int)iterator - (int)path;
|
185
|
+
char *word = (char*)malloc(word_length + 1);
|
186
|
+
strncpy(word, path, word_length);
|
187
|
+
word[word_length] = '\0';
|
188
|
+
VALUE rb_word = rb_str_new2((const char*)word);
|
189
|
+
|
190
|
+
if(include_value) {
|
191
|
+
sb_trie_state_walk(state, (TrieChar)'\0');
|
192
|
+
|
193
|
+
VALUE return_ary = rb_ary_new();
|
194
|
+
rb_ary_push(return_ary, rb_word);
|
195
|
+
TrieData trie_data = sb_trie_state_get_data(state);
|
196
|
+
rb_ary_push(return_ary, INT2FIX(trie_data));
|
197
|
+
return return_ary;
|
198
|
+
} else
|
199
|
+
return rb_word;
|
200
|
+
}
|
201
|
+
|
202
|
+
if(!sb_trie_state_is_walkable(state, *iterator))
|
203
|
+
return Qnil;
|
204
|
+
|
205
|
+
sb_trie_state_walk(state, *iterator);
|
206
|
+
iterator++;
|
207
|
+
}
|
208
|
+
|
209
|
+
return Qnil;
|
210
|
+
}
|
211
|
+
|
157
212
|
static VALUE trie_get_path(VALUE self) {
|
158
213
|
return rb_iv_get(self, "@path");
|
159
214
|
}
|
@@ -167,8 +222,9 @@ void Init_trie() {
|
|
167
222
|
rb_define_method(cTrie, "path", trie_get_path, 0);
|
168
223
|
rb_define_method(cTrie, "has_key?", trie_has_key, 1);
|
169
224
|
rb_define_method(cTrie, "get", trie_get, 1);
|
170
|
-
rb_define_method(cTrie, "add", trie_add,
|
225
|
+
rb_define_method(cTrie, "add", trie_add, -2);
|
171
226
|
rb_define_method(cTrie, "delete", trie_delete, 1);
|
172
227
|
rb_define_method(cTrie, "close", trie_close, 0);
|
173
228
|
rb_define_method(cTrie, "children", trie_children, 1);
|
229
|
+
rb_define_method(cTrie, "walk_to_terminal", trie_walk_to_terminal, -2);
|
174
230
|
}
|
data/spec/trie_spec.rb
CHANGED
@@ -48,6 +48,11 @@ describe Trie do
|
|
48
48
|
@trie.add('forsooth').should == true
|
49
49
|
@trie.get('forsooth').should == -1
|
50
50
|
end
|
51
|
+
|
52
|
+
it 'adds a word with a weight to the trie' do
|
53
|
+
@trie.add('chicka',123).should == true
|
54
|
+
@trie.get('chicka').should == 123
|
55
|
+
end
|
51
56
|
end
|
52
57
|
|
53
58
|
describe :delete do
|
@@ -76,4 +81,22 @@ describe Trie do
|
|
76
81
|
children.should include('rocket')
|
77
82
|
end
|
78
83
|
end
|
84
|
+
|
85
|
+
describe :walk_to_terminal do
|
86
|
+
it 'returns the first word found along a path' do
|
87
|
+
@trie.add 'anderson'
|
88
|
+
@trie.add 'andreas'
|
89
|
+
@trie.add 'and'
|
90
|
+
|
91
|
+
@trie.walk_to_terminal('anderson').should == 'and'
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'returns the first word and value along a path' do
|
95
|
+
@trie.add 'anderson'
|
96
|
+
@trie.add 'andreas'
|
97
|
+
@trie.add 'and', 15
|
98
|
+
|
99
|
+
@trie.walk_to_terminal('anderson',true).should == ['and', 15]
|
100
|
+
end
|
101
|
+
end
|
79
102
|
end
|