Reputation: 109
I'm trying to convert a string of morse code into words. I split the string into words. Then I split each word into a secondary array of letters and numbers.
def self.decode(str)
decoded = ""
arr = []
p arr = str.split(' ')
p arr.map! { |i| i.split(' ') }
arr.each do |r|
r.each do |i|
decoded += @morse.invert[i].to_s[-1]
end
end
p decoded
end
In my hash, I use numbers. They start with N
. In to_s[-1]
, the -1
is to drop the N
.
I get this error:
`+': no implicit conversion of nil into String
I can figure out how to get past it though because I don't see a nil
value in the array.
class Morse
@morse = {
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: '--..',
' ': ' ' ,
N1: '.----',
N2: '..---',
N3: '...--',
N4: '....-',
N5: '.....',
N6: '-....',
N7: '--...',
N8: '---..',
N9: '----.',
N0: '-----'
}
def self.encode(str)
encoded = ""
sym_temp = ""
str = str.upcase!
str.each_char do |c|
ascii_check = c.ord
if ascii_check.between?(65,90)
temp = str[c].to_sym
encoded += "#{@morse[temp]}" + " "
elsif ascii_check.between?(48,57)
temp = "N".concat(str[c]).to_sym
encoded += "#{@morse[temp]}" + " "
elsif ascii_check ===(32)
temp = str[c].to_sym
encoded += "#{@morse[temp]}"
end
end
p encoded
end
def self.decode(str)
decoded = ""
arr = []
# str.split(' ').map do |i|
p arr = str.split(' ')
p arr.map! { |i| i.split(' ') }
arr.each do |r|
r.each do |i|
p decoded += @morse.invert[i].to_s[-1].to_s
end
end
p decoded
end
# def self.read_file
# # @Temp = File.read("preamble_encode.txt").chomp
# # File.open('hiscore.txt'){|f| f.lines.map{|l| l.chomp!.split(',')}}
# # @Temp = File.foreach("preamble_encode.txt", 'r') {|f| f.lines.map{|l| l.chomp}}
# end
# def self.write_file
# # Temp2 = File.open('preamble_decode.txt', 'w') do |f|
# # f.puts Temp2
# # end
# end
end
test = "Abc 1oL!"
test2 = ".-- . - .... . .--. . --- .--. .-.. ."
Morse.encode(test)
Morse.decode(test2)
Upvotes: 1
Views: 324
Reputation: 110665
As you question has been answered, I would like to suggest how you may write methods for coding and decoding.
Firstly, the keys of your hash should be strings rather than symbols, as the hash is being used to code strings, which are made up of single-character strings. We also need the digits to be, '0'
to '9'
rather than 'N0'
to 'N9'
. Spaces are represented by time delays equal to seven dots, rather than combinations of dots and dashes, so I've represented spaces by the string '<delay>'
. See the Morse Wiki.
Since the hash won't change, I've made it a constant rather than the value of an instance variable.
CharactersToMorse = {
'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' => '--..' , ' ' => '<delay>', '0' => '-----', '1' => '.----',
'2' => '..---', '3' => '...--', '4' => '....-', '5' => '.....', '6' => '-....',
'7' => '--...', '8' => '---..', '9' => '----.'
}
We will need to decode, so I'll assign the inverted hash to a constant as well.
MorseToCharacters = CharactersToMorse.invert
#=> {".-"=>"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", "<delay>"=>" ", "-----"=>"0", ".----"=>"1", "..---"=>"2",
# "...--"=>"3", "....-"=>"4", "....."=>"5", "-...."=>"6", "--..."=>"7",
# "---.."=>"8", "----."=>"9"}
Our methods for coding and decoding are now very simple.
def code(text)
text.each_char.map { |c| CharactersToMorse[c] }
end
def decode(morse)
morse.map { |m| MorseToCharacters[m] }.join(' ')
end
Let's try it.
text = "NOW IS THE TIME FOR 47 RUBIESTS TO COME TO THE AID OF THEIR BOWLING TEAM"
morse = code(text)
#=> ["-.", "---", ".--", "<delay>", "..", "...", "<delay>", "-", "....",
# ".", "<delay>", "-", "..", "--", ".", "<delay>", "..-.", "---", ".-.",
# "<delay>", "....-", "--...", "<delay>", ".-.", "..-", "-...", "..",
# ".", "...", "-", "...", "<delay>", "-", "---", "<delay>", "-.-.", "---",
# "--", ".", "<delay>", "-", "---", "<delay>", "-", "....", ".", "<delay>",
# ".-", "..", "-..", "<delay>", "---", "..-.", "<delay>", "-", "....",
# ".", "..", ".-.", "<delay>", "-...", "---", ".--", ".-..", "..", "-.",
# "--.", "<delay>", "-", ".", ".-", "--"]
decode(morse)
#=> "NOW IS THE TIME FOR 47 RUBIESTS TO COME TO THE AID OF THEIR BOWLING TEAM"
If for some reason the keys of CharactersToMorse
must be symbols, change the methods to:
def code(text)
text.each_char.map { |c| CharactersToMorse[c.to_sym] }
end
def decode(morse)
morse.map { |m| MorseToCharacters[m].to_s }.join(' ')
end
Upvotes: 3
Reputation: 1511
Your problem is here:
:P => :'.--.',
Your colon on the right hand side of the hash rocket is making that a symbol, not a string. As it happens, your test case for decode includes a P. When you try to look up the String '.--.', it doesn't find it and returns nil.
Upvotes: 5