1
2
3
4
5
6
7 require 'pp'
8
9 class Hash
10
11 def deep_merge!(second)
12
13 merger = proc { |key,v1,v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
14 self.merge!(second, &merger)
15 end
16
17 def nested_hash(array)
18 node = self
19 array.each do |i|
20 node[i]=Hash.new if node[i].nil?
21 node = node[i]
22 end
23 self
24 end
25
26 def merge_nested_hash!(nested_hash)
27 deep_merge!(nested_hash)
28 end
29
30
31
32
33 def each_trie_path
34 raise ArgumentError unless block_given?
35 self.class.each_trie_path(self) { |path, object| yield(path, object) }
36 end
37
38 protected
39 def self.each_trie_path(object, path = [], &block)
40
41 if object.is_a?(Hash)
42 object.each do |key, value|
43
44 if key == true && value == {}
45 if path == [:root]
46 yield(path, {true=>{}})
47 next
48 end
49 yield(path, object)
50 end
51
52 self.each_trie_path(value, [path , key].flatten, &block)
53 end
54 else
55 yield(path, object)
56 end
57 end
58
59 end
60
61
62 class Trie
63
64 @hash = Hash.new.merge_nested_hash!(Hash.new)
65
66
67 class << self; attr_accessor :hash; end
68
69 def initialize
70 Trie.hash.merge_nested_hash!({:root=>{}})
71 end
72
73
74 def add_int(int)
75 ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }
76 ia.unshift(:root).push(true)
77 Trie.hash.merge_nested_hash!(Hash.new.nested_hash(ia))
78 end
79
80 def matchi(int)
81 ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }
82 node = Trie.hash.fetch(:root,nil)
83 ia.each do |digit|
84 node = node[digit]
85
86 return false unless node
87 end
88 node.fetch(true,nil) ? true : false
89 end
90
91 def mfpi(int)
92 ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }
93 node = Trie.hash.fetch(:root,nil)
94 ia.each do |digit|
95 node = node[digit]
96 return false unless node
97 end
98 return true
99 end
100
101
102 def add_word(word)
103 ca = word.split(//u)
104 ca.unshift(:root).push(true)
105 Trie.hash.merge_nested_hash!(Hash.new.nested_hash(ca))
106 end
107
108 def match(word)
109 ca = word.split(//u)
110 node = Trie.hash.fetch(:root,nil)
111 ca.each do |char|
112 node = node[char]
113
114 return false unless node
115 end
116 node.fetch(true,nil) ? true : false
117 end
118
119 def mfpw(word)
120 ca = word.split(//u)
121 node = Trie.hash.fetch(:root,nil)
122 ca.each do |char|
123 node = node[char]
124 return false unless node
125 end
126 return true
127 end
128
129 end
130
131
132 trie = Trie.new
133 p Trie.hash
134
135 trie.add_word("word")
136 pp Trie.hash
137 p trie.match("word")
138 p trie.match("word2")
139 trie.add_word("word2")
140 p trie.match("word2")
141 pp Trie.hash
142
143 trie.add_word("")
144 p trie.match("")
145 pp Trie.hash
146
147 puts
148
149 p trie.match("word")
150 p trie.mfpw("wor")
151
152 puts
153
154 trie.add_int(12345)
155 p Trie.hash
156
157 trie.add_int(12980345)
158 pp Trie.hash
159
160 trie.add_int(8512)
161 pp Trie.hash
162 p trie.matchi(8512)
163 p trie.matchi(85)
164 p trie.mfpi(85)
165 p trie.matchi(51)
166
167 puts
168
169 puts
170 pp Trie.hash
171 paths = []
172 Trie.hash.each_trie_path { |path, value| paths.push([ path ]) }
173
174
175 puts
176 paths.each { |x| p x }
177 puts
178
179
180
181
182
183 require 'pp'
184
185 class Hash
186 def Hash.new_nested_hash
187 Hash.new{|h,k| h[k]=Hash.new(&h.default_proc) }
188 end
189 end
190
191
192 class Trie
193
194 @hash = Hash.new_nested_hash
195
196 class << self; attr_accessor :hash; end
197
198 def <<(word)
199 ca = word.split(//u)
200 wl = ca.size
201 str = ""
202 wl.times { |x| str << "[ca.at(#{x})]" }
203 str = "Trie.hash" << str << "[true]"
204
205 eval(str)
206 end
207
208
209 def match(word)
210 ca = word.split(//u)
211 wl = ca.size
212 str = ""
213
214 wl.times { |x| str << ".fetch(ca.at(#{x}),nil)" }
215 str = "Trie.hash" << str << ".fetch(true,nil)"
216
217 ret = eval(str) rescue nil
218
219
220
221
222
223
224
225
226
227 ret == {} ? true : false
228 end
229
230 end
231
232
233 trie = Trie.new
234 trie << "word"
235 pp Trie.hash
236 p trie.match("word")
237 p trie.match("word2")
238 trie << "word2"
239 p trie.match("word2")
240 pp Trie.hash
241
242 trie << ""
243 p trie.match("")
244 pp Trie.hash
245
246
247
248
249
250
251
252 require 'pp'
253
254 class Hash
255 def Hash.new_nested_hash
256 Hash.new{|h,k| h[k]=Hash.new(&h.default_proc) }
257 end
258 end
259
260
261 class Hash
262
263
264
265
266 def each_trie_path
267 raise ArgumentError unless block_given?
268 self.class.each_trie_path(self) { |path, object| yield(path, object) }
269 end
270
271 protected
272 def self.each_trie_path(object, path = [], &block)
273
274 if object.is_a?(Hash)
275 object.each do |key, value|
276
277 if key == true && value == {}
278 if path == [:root]
279 yield(path, {true=>{}})
280 next
281 end
282 yield(path, object)
283 end
284
285 self.each_trie_path(value, [path , key].flatten, &block)
286 end
287 else
288 yield(path, object)
289 end
290 end
291
292 end
293
294
295 class Trie
296
297 @hash = Hash.new_nested_hash
298 class << self; attr_accessor :hash; end
299
300 def initialize
301 Trie.hash[:root]
302 end
303
304
305 def add_int(int)
306 ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }
307 ia.unshift(:root)
308 str = ""
309 ia.size.times { |x| str << "[ia.at(#{x})]" }
310 str = "Trie.hash" << str << "[true]"
311 eval(str)
312 end
313
314 def matchi(int)
315 ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }
316 node = Trie.hash.fetch(:root,nil)
317 ia.each do |digit|
318 node = node.fetch(digit,nil)
319 return false unless node
320 end
321 node.fetch(true,nil) ? true : false
322 end
323
324 def mfpi(int)
325 ia = int.to_s.scan(/[[:digit:]]/).map { |i| i.to_i }
326 node = Trie.hash.fetch(:root,nil)
327 ia.each do |digit|
328 node = node.fetch(digit,nil)
329 return false unless node
330 end
331 return true
332 end
333
334
335 def <<(word)
336 ca = word.split(//u)
337 ca.unshift(:root)
338
339
340 str = ""
341 ca.size.times { |x| str << "[ca.at(#{x})]" }
342 str = "Trie.hash" << str << "[true]"
343
344 eval(str)
345 end
346
347 def match(word)
348 ca = word.split(//u)
349 ca.unshift(:root)
350
351
352 str = ""
353 ca.size.times { |x| str << ".fetch(ca.at(#{x}),nil)" }
354 str = "Trie.hash" << str << ".fetch(true,nil)"
355
356 ret = eval(str) rescue nil
357
358
359
360
361
362
363
364
365
366 ret == {} ? true : false
367 end
368
369 def match2(word)
370 ca = word.split(//u)
371 node = Trie.hash.fetch(:root,nil)
372 ca.each do |char|
373 node = node.fetch(char,nil)
374 return false unless node
375 end
376 node.fetch(true,nil) ? true : false
377 end
378
379 def mfpw(word)
380 ca = word.split(//u)
381 node = Trie.hash.fetch(:root,nil)
382 ca.each do |char|
383 node = node.fetch(char,nil)
384 return false unless node
385 end
386 return true
387 end
388
389 end
390
391
392 trie = Trie.new
393 trie << "word"
394 pp Trie.hash
395 p trie.match("word")
396 p trie.match("word2")
397 trie << "word2"
398 p trie.match("word2")
399 pp Trie.hash
400
401 trie << ""
402 p trie.match("")
403 pp Trie.hash
404
405 puts
406
407 p trie.match2("word")
408 p trie.mfpw("wor")
409
410 puts
411
412 trie.add_int(8512)
413 pp Trie.hash
414 p trie.matchi(8512)
415 p trie.matchi(85)
416 p trie.mfpi(85)
417 p trie.matchi(51)
418
419 puts
420
421 puts
422 pp Trie.hash
423 paths = []
424 Trie.hash.each_trie_path { |path, value| paths.push([ path ]) }
425
426
427 puts
428 paths.each { |x| p x }
429 puts