Created
May 4, 2012 01:16
-
-
Save Bill/2590929 to your computer and use it in GitHub Desktop.
Solution to http://www.therubygame.com/challenges/6 relying on Ruby Regexp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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