rubyhasht9

Tweaking a T9 Trie in Ruby to append new words


This implementation of a T9 trie generator has a major flaw. It's overwriting previous words added to the tree rather than appending them. I'm not surprised at it, just stumped...

class Trie
  def initialize
    @root = Hash.new
  end

# do a for loop here
  def build(word) 
    node = @root
    t9num = word.tr('a-z', '22233344455566677778889999')
    t9num.each_char do |ch|
      node[ch] ||= Hash.new
      node = node[ch]
    end
    node[:end] = "#{word}"
  end

  def find(str) 
    node = @root
    str.each_char do |ch|
      return nil unless node = node[ch]
    end
    node[:end] && true
  end
end

These commands:

t = Trie.new
t.build('buy')
t.build('build')
t.build('builder')
t.build('act')
t.build('acu')
puts t.inspect

Output this:

#<Trie:0x0000010103ea60 @root={"2"=>{"8"=>{"9"=>{:end=>"buy"}, "4"=>{"5"=>{"3"=>{:end=>"build", "3"=>{"7"=>{:end=>"builder"}}}}}}, "2"=>{"8"=>{:end=>"acu"}}}}>

Solution

  • It seems to me that the problem is in this line:

    node[:end] = "#{word}"
    

    Here your node[:end] can only be one word, and it is overwritten if two words have the same sequence of t9 keys. Try this instead:

    (node[:end] ||= []) << word
    

    This way you will have an array of words at the end of the branch. Don't forget to check if the word is already in the trie.