Morse Code Translator in Ruby

I got a challenge from my friend Kim to solve a programming problem they give new hire candidates.  Basically, the problem is to build something that takes a string of Morse code and returns all possible translations for it.  I did my solution in Ruby.  This is pretty much a first pass,  so comments are appreciated.  This is, I think, the first time I’ve ever solved a problem with recursion when I wasn’t specifically told “use recursion” for an assignment.


def morse_code()
  morse = {'a' => '.-',
              'b' => '-...',
              'c' => '-.-.',
              'd' =>'-..',
              'e' => '.',
              'f' => '..-.',
              'g' => '--.',
              'h' => '....',
              'i' => '..',
              'j' => '.---',
              'k' => '-.-',
              'l' => '.-..',
              'm' => '--',
              'n' => '-.',
              'o' => '---',
              'p' => '.--.',
              'q' => '--.-',
              'r' => '.-.',
              's' => '...',
              't' => '-',
              'u' => '..-',
              'v' => '...-',
              'w' => '.--',
              'x' => '-..-',
              'y' => '-.--',
              'z' => '--..'}
  
  # This is a hack; I reversed the hash when I typed it and didn't want to retype
  # just for a proof of concept
  morse.invert
end

def read_morse_code(input, morse)
  
  # Initialize some arrays
  code_matches = Array.new
  matches = Array.new
  translation_list = Array.new
  
  # If we've been passed a nil input, it's at the end of the search.
  # Return an empty array
  if input.nil?
    return translation_list  << ''
  end
  
  # Collect any matches with the morse code at the start of the string
  # and delete the nils; the collect block returns nil values when there's no match
  code_matches = morse.collect {|code, letter| input.match('^' + Regexp.escape(code))}
  code_matches.delete(nil)
  
  code_matches.each do |code_match|
    temp_input = String.new(input)
    
    if temp_input == code_match.to_s
      translation_list << morse[code_match.to_s]
    else
      matches = read_morse_code(temp_input.gsub!(Regexp.new('^' + Regexp.escape(code_match.to_s)), ''), morse)
      # Stick each match into the translation_list
      matches.each do |match|
        translation_list << morse[code_match.to_s] + match
      end
    end
    
  end
  
  # Remove any nil matches and return what we've got
  translation_list.delete(nil)
  return translation_list
  
end

# Grab the morse_code hash
morse = morse_code
translations = read_morse_code(String.new(ARGV[0]), morse)

translations.each do |translation|
  puts translation
end

This entry was posted in Coding. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *