Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Solution to http://www.therubygame.com/challenges/6 relying on Ruby Regexp
require 'singleton'
# This is a parser pattern based on regexp as lexer.
# Express your tokens as parenthesized regexps separated by
# alternation (|). Erroneous input causes immediate return.
module Parse
def parse( s, p, &block)
i = 0
while i < s.length do
# could pass i to match and use block form in newer lib
m = s[i..-1].match(p)
if m
block.call(m) # call block with match data
i += m.end(0)
else
# unexpected input terminates with no error
i = s.length # extend pattern here to support recovery!
end
end
end
end
class MorseRegexp
include Parse
include Singleton # only build the lookup once
# def self.instance
# self.new
# end
def decode(s)
result = ''
parse(s, @tokenizer) do |m|
if m[3] # between letters
# no-op
elsif m[2] # between words
result << ' '
else # letter
result << self[m[1]]
end
end
result
end
def initialize
@lookup = Array.new( 3**4 - 1 ) # addressable via a four-digit ternary number
codes = <<END # http://www.therubygame.com/challenges/6
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 --..
END
parse(codes, /\A([[:alpha:]])\s+([\.-]{1,4})\s*/) do |m|
self[m[2]] = m[1]
end
@tokenizer = /\A([\.-]{1,4})|(\s{3})|(\s)/
end
def [](m)
@lookup[idx(m)]
end
def []=(m,c)
@lookup[idx(m)] = c
end
private
def idx(m) # convert morse code string to four-digit ternary number
m.rjust(4).tr(' .-', '012').to_i(3)
end
end
MorseRegexp.instance.decode(morse)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.