Из ката я понимаю, что буквы должны быть разделены одним пробелом, а слова - тремя пробелами.
В качестве первого шага я внесу два изменения в хэш morse_dict
: удалите ключ ' '
;и добавить пары ключ-значение для некоторых знаков препинания.Клавиша пробела не нужна;Необходимость кодов пунктуации обсуждается в ката.
PUNCTUATION = { "."=>".-.-.-", ","=>"--..--", "?"=>"..--..", "!"=>"-.-.--" }
ALPHA_TO_MORSE = dict.reject { |k,_| k == " " }.merge(PUNCTUATION)
#=> {"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"=>"--..", "1"=>".----", "2"=>"..---", "3"=>"...--",
# "4"=>"....-", "5"=>".....", "6"=>"-....", "7"=>"--...", "8"=>"---..",
# "9"=>"----.", "0"=>"-----", "."=>".-.-.-", ","=>"--..--", "?"=>"..--..",
# "!"=>"-.-.--"}
Я получил азбуку Морзе для символов пунктуации из Вики Морзе .При желании можно добавить дополнительные знаки пунктуации.
Хеш ALPHA_TO_MORSE
используется при кодировании текста.Обратное значение этого хэша необходимо для декодирования сообщений в азбуке Морзе.Также для декодирования необходима пара ключ-значение "...---..."=>"sos"
.
MORSE_TO_ALPHA = ALPHA_TO_MORSE.invert.merge("...---..."=>"sos")
#=> {".-"=>"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", ".----"=>"1", "..---"=>"2", "...--"=>"3",
# "....-"=>"4", "....."=>"5", "-...."=>"6", "--..."=>"7", "---.."=>"8",
# "----."=>"9", "-----"=>"0", ".-.-.-"=>".", "--..--"=>",",
# "..--.."=>"?", "-.-.--"=>"!""...---..."=>"sos"}
Еще один хеш необходим для обработки случаев, когда сообщение "sos"
(или "SOS"
- азбука Морзе нечувствительна к регистру)или "sos"
, за которым следует знак пунктуации (например, "sos!"
), должны быть закодированы. 1 См. вики.
SOS_WITH_PUNCTUATION = PUNCTUATION.each_with_object({}) { |(k,v),h|
h["sos#{k}"] = "...---... #{v}" }.merge('sos'=>"...---...")
#=> {"sos."=>"...---... .-.-.-", "sos,"=>"...---... --..--",
# "sos?"=>"...---... ..--..", "sos!"=>"...---... -.-.--", "sos"=>"...---..."}
Ниже приведены методы кодирования и декодирования.encode
проверяет, является ли каждое слово в строке ключом в хэше SOS_WITH_PUNCTUATION
.Если это так, значение ключа - это азбука Морзе для слова;иначе слово делится на буквы, и каждая буква переводится на азбуку Морзе.
def encode(str)
str.strip.downcase.split.map do |word|
if SOS_WITH_PUNCTUATION.key?(word)
SOS_WITH_PUNCTUATION[word]
else
word.each_char.map { |c| ALPHA_TO_MORSE[c] }.join(' ')
end
end.join (' ')
end
def decode(morse)
morse.strip.split(/ {3}/).map do |word|
word.split.map { |c| MORSE_TO_ALPHA[c] }.join
end.join(' ')
end
Теперь мы можем попробовать эти два метода.
str = " Is now the time for you, and 007, to send an SOS?"
morse = encode str
#=> ".. ... -. --- .-- - .... . - .. -- . ..-. --- .-. -.-- --- ..- --..-- .- -. -.. ----- ----- --... --..-- - --- ... . -. -.. .- -. ...---... ..--.."
decode morse
#=> "is now the time for you, and 007, to send an sos?"
1 Было бы проще иметь этап предварительной обработки, который преобразовал бы, скажем, "sos."
в "sos ."
, но когда полученный код Морзе был декодирован тамбудет промежуток между "sos"
и "."
.Я полагаю, что криптографы могли бы справиться с этим, но я решил избежать вставки пробела.