Ruby Quiz <james <at> grayproductions.net> writes: > This week's quiz is to write program that displays all possible translations > for ambiguous words provided in code. Wow, a ruby quiz with no discussion or clarifications? Sounds easy enough for me to have a go at my second ruby quiz entry: ############################# class String # Calls the given block for every substring with length given in +range+ # # Yields the string's head [0..i] and tail [i..-1] for each i in +range+ def each_substr(range = [1,self.length]) raise ArgumentError, "Block required" unless block_given? range.first.upto([self.length, range.last].min) do |i| yield [ self[0...i], self[i..-1] ] end end end class Morse # Windows users like me don't have a dictionary, so use your own if you like Dictionary = ['i', 'a', 'an', 'emu', 'pet', 'sofia', 'eugenia'] Letters = { '.-' => :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, } def initialize code raise ArgumentError, "Invalid morse code string" unless code.match(/^[.-]+$/) self.string = code end def string=(newstring) @string = newstring @words = nil end # Run the calculation and save each result with a boolean indicating whether # it's in the dictionary or not def words @words ||= self.class.permutate(@string).sort.map do |word| [Dictionary.include?(word), word] end end class << self # Generate all valid 'words' from a morse code string def permutate morse results = [] # Grab the next 1-4 letters from the string morse.each_substr(1..4) do |substr, rest| letter = Letters[substr] if letter # If this substring is a letter, calculate sub-permutations # (using the remaining part of the string) permutations = permutate(rest) if permutations.empty? results << "#{letter}" else # Add each sub-permutation to the current letter, and add that to # the list of results permutations.each do |permutation| results << "#{letter}#{permutation}" end end end end results end # Turns a string back into its morse code form def morsify string, separator = '|' string.split(//).map do |letter| Letters.invert[letter.intern] end.join separator end end end if __FILE__ == $0 while (line = gets.chomp) && !line.empty? begin out = Morse.new(line).words.map do |in_dict, word| "%-#{line.length+2}s %s" % [(in_dict ? "[#{word}]" : " #{word}"), "#{Morse.morsify word}"] end rescue ArgumentError => e out = "Invalid morse code string ('#{line}')" end puts out end end