# \[QUIZ\] Morse Code (#121)

**URL:** <https://www.ruby-forum.com/t/quiz-morse-code-121/92764>\
**Category:** Ruby\
**Created:** [April 24, 2007, 12:16am UTC](https://www.ruby-forum.com/t/quiz-morse-code-121/92764 "2007-04-24T00:16:06Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![MenTaLguY](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/439d5e/32.png) [@MenTaLguY](https://www.ruby-forum.com/u/MenTaLguY)\
**Post date:** [April 24, 2007, 12:16am UTC](https://www.ruby-forum.com/t/quiz-morse-code-121/92764/1 "2007-04-24T00:16:06Z")

</div>

I’ve made no particular effort to make this solution efficient, but I  
had fun writing it.

MORSE = Hash[\*%w(  
A .- N -.  
B -… O —  
C -.-. P .–.  
D -… Q --.-  
E . R .-.  
F …-. S …  
G --. T -  
H … U …-  
I … V …-  
J .— W .–  
K -.- X -…-  
L .-… Y -.–  
M – Z --…  
)].invert.freeze

class Decoder  
Arc = Struct.new :input, :to, :output  
State = Struct.new :arcs  
Solution = Struct.new :state, :output

def initialize(code)  
@start = State[[]]  
code.each do |input, output|  
raise ArgumentError, “input cannot be empty” if input.empty?  
branch = input.reverse.unpack(“C\*”).inject(@start) do |state, c|  
string, output = output, “”  
State[[Arc[c, state, string]]]  
end  
@start.arcs += branch.arcs  
end  
end

def process(input)  
input.unpack(“C\*”).inject([Solution[@start, “”]]) do |solutions, c|  
break [] if solutions.empty?  
solutions.map do |solution|  
solution.state.arcs.select do |arc|  
arc.input == c  
end.map do |arc|  
Solution[arc.to, solution.output + arc.output]  
end  
end.flatten  
end.select do |solution|  
solution.state == @start  
end.map do |solution|  
solution.output  
end  
end  
end

Decoder.new( MORSE ).process( gets.chomp ).sort.each do |result|  
puts result  
end

---

<div class="post-metadata">

**Author:** ![MenTaLguY](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/439d5e/32.png) [@MenTaLguY](https://www.ruby-forum.com/u/MenTaLguY)\
**Post date:** [April 24, 2007, 1:51am UTC](https://www.ruby-forum.com/t/quiz-morse-code-121/92764/2 "2007-04-24T01:51:12Z")

</div>

Here’s a slightly fixed version – notably, for a Struct, you must use  
equal? for object identity rather than == (and the latter can be a bit  
deadly if you’re dealing with a recursive data structure as we are here  
for the state machine). The changes to initialize are just cosmetic,  
though.

MORSE = Hash[\*%w(  
A .- N -.  
B -… O —  
C -.-. P .–.  
D -… Q --.-  
E . R .-.  
F …-. S …  
G --. T -  
H … U …-  
I … V …-  
J .— W .–  
K -.- X -…-  
L .-… Y -.–  
M – Z --…  
)].invert.freeze

class Decoder  
Arc = Struct.new :input, :to, :output  
State = Struct.new :arcs  
Solution = Struct.new :state, :output

def initialize(code)  
@start = State.new  
@start.arcs = code.map do |input, output|  
raise ArgumentError, “input cannot be empty” if input.empty?  
input.reverse.unpack(“C\*”).inject(@start) do |state, c|  
string, output = output, “”  
State[[Arc[c, state, string]]]  
end.arcs  
end.flatten  
end

def process(input)  
input.unpack(“C\*”).inject([Solution[@start, “”]]) do |solutions, c|  
break [] if solutions.empty?  
solutions.map do |solution|  
solution.state.arcs.select do |arc|  
arc.input == c  
end.map do |arc|  
Solution[arc.to, solution.output + arc.output]  
end  
end.flatten  
end.select do |solution|  
solution.state.equal? @start  
end.map do |solution|  
solution.output  
end  
end  
end

Decoder.new( MORSE ).process( gets.chomp ).sort.each do |result|  
puts result  
end
