wikiti
8/1/2018 - 9:14 AM

Trie implementation in Ruby

A simple implementation for a trie tree in ruby. For more information, check this:

https://en.wikipedia.org/wiki/Trie

# A basic ruby implementation for the trie structure.
class Trie
  # Node class to store node information (character or tag, and action)
  class Node
    attr_reader :children, :tag
    attr_accessor :value

    def initialize(tag, parent, action = nil)
      @tag = tag
      parent.children << self if parent
      @children = []
      @action = action
    end

    def find_child(tag)
      children.find { |node| node.tag == tag }
    end
  end

  # Initialize the trie with an empty root node
  def initialize(name = nil)
    @root = Node.new(name, nil)
  end

  # Add a new set of nodes to the trie.
  def add(string, value)
    current = @root

    string.chars.each do |tag|
      current = current.find_child(tag) || Node.new(tag, current, nil)
    end

    current.value = value
  end

  # Execute a node action given a string. If no node is found, nothing is executed.
  def value(string)
    node = find_node(string)
    node.value if node
  end

  # Pretty print the trie recursively
  def pretty_print(current = @root, level = 0, indent = ' ')
    puts "#{indent * level}#{current.tag}#{current.value ? " (#{current.value})" : ''}"
    current.children.each { |child| pretty_print(child, level + 1, indent) }
  end

  private

  # Traverse the trie to find a node
  def find_node(string)
    current = @root

    string.chars.each do |tag|
      current = current.find_child(tag)
      return if current.nil?
    end

    current
  end
end

# Run example
# ---

trie = Trie.new 'trie_example'

trie.add 'zero', 0
trie.add 'one', 1
trie.add 'two', 2
trie.add 'point', ->(x, y) { "Point #{x},#{y}" }

puts trie.value('zero'), trie.value('one'), trie.value('two'), trie.value('three')
puts trie.value('point').call(41, 42)

trie.pretty_print