Here's a slight optimization to the each_translation method in my original
submission:

class String
  # Yield once for each translation of this (Morse code) string.
  def each_translation
    split(//).each_grouping(MinCodeLength, MaxCodeLength) do |group|
      valid = true
      group.map! do |char_arr|
        # Convert arrays of individual dots & dashes to strings, then translate.
        letter = Decode[char_arr.join]
        letter.nil? ? (valid = false; break) : letter
      end
      # Join all the translated letters into one string.
      yield group.join if valid
    end
  end
end

Originally, I would translate every letter in a word, and then throw it out if
any failed to translate. This version breaks out of the map! as soon as any
letter fails, at the expense of two more variables and a few more LOC. I
expected this to speed it up quite a bit, but this test data shows only a
minor improvement for short code strings:

# (All times in seconds)
# Length, Original Time, New Time
0          0.112          0.113
1          0.110          0.109
2          0.106          0.108
3          0.106          0.106
4          0.106          0.106
5          0.108          0.107
6          0.121          0.119
7          0.123          0.121
8          0.125          0.124
9          0.132          0.130
10         0.146          0.145
11         0.188          0.187
12         0.259          0.253
13         0.403          0.390
14         0.713          0.668
15         1.313          1.221
16         2.513          2.342
17         4.959          4.597
18         9.885          9.146
19        19.671         18.208
20        38.729         35.972
21        78.767         71.431
22       159.931        145.794
23       319.763        294.711
24       636.660        590.360
25      1273.474       1169.021

These were all run with prefixes of '...---..-....--.--.-...-.'
The percentage improvement increases as the length of the code to translate
increases, as can be seen in this (noisy) plot:

http://www.jessemerriman.com/images/ruby_quiz/121_morse_code/new_vs_old.png

How far it goes down after that, I don't know, but my guess would be that
eventually it'd approach zero.

-- 
Jesse Merriman
jessemerriman / warpmail.net
http://www.jessemerriman.com/