Ruby Iterating over an array and find match in an hash and replace the element in array
up vote
1
down vote
favorite
I would like someone to clarify how can I possibly iterating over an array, find an exact match in an hash[value], and replace the element in the array with the hash[key].
As example, if I have a morse directory morse_dict = {
"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" => "-----"
}
and I want a method that for a given string in morse code returns a string in regular alphabet.
This is the codewars kata.
I am not interested in the solution to the challenge itself, I would like to understand the principle of this.
So far I have thought of proceeding this way:
def morse_code(arr)
arr.split(" ").each {|element|
element.each_char {|char|
(morse_dict.include?(char)) ? (print "true") : (print "false")}
}
end
I only print false, which means that I am not actually looking for match into the hash.
arrays ruby hash iteration
add a comment |
up vote
1
down vote
favorite
I would like someone to clarify how can I possibly iterating over an array, find an exact match in an hash[value], and replace the element in the array with the hash[key].
As example, if I have a morse directory morse_dict = {
"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" => "-----"
}
and I want a method that for a given string in morse code returns a string in regular alphabet.
This is the codewars kata.
I am not interested in the solution to the challenge itself, I would like to understand the principle of this.
So far I have thought of proceeding this way:
def morse_code(arr)
arr.split(" ").each {|element|
element.each_char {|char|
(morse_dict.include?(char)) ? (print "true") : (print "false")}
}
end
I only print false, which means that I am not actually looking for match into the hash.
arrays ruby hash iteration
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I would like someone to clarify how can I possibly iterating over an array, find an exact match in an hash[value], and replace the element in the array with the hash[key].
As example, if I have a morse directory morse_dict = {
"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" => "-----"
}
and I want a method that for a given string in morse code returns a string in regular alphabet.
This is the codewars kata.
I am not interested in the solution to the challenge itself, I would like to understand the principle of this.
So far I have thought of proceeding this way:
def morse_code(arr)
arr.split(" ").each {|element|
element.each_char {|char|
(morse_dict.include?(char)) ? (print "true") : (print "false")}
}
end
I only print false, which means that I am not actually looking for match into the hash.
arrays ruby hash iteration
I would like someone to clarify how can I possibly iterating over an array, find an exact match in an hash[value], and replace the element in the array with the hash[key].
As example, if I have a morse directory morse_dict = {
"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" => "-----"
}
and I want a method that for a given string in morse code returns a string in regular alphabet.
This is the codewars kata.
I am not interested in the solution to the challenge itself, I would like to understand the principle of this.
So far I have thought of proceeding this way:
def morse_code(arr)
arr.split(" ").each {|element|
element.each_char {|char|
(morse_dict.include?(char)) ? (print "true") : (print "false")}
}
end
I only print false, which means that I am not actually looking for match into the hash.
arrays ruby hash iteration
arrays ruby hash iteration
edited Nov 14 at 23:10
Cary Swoveland
66.8k53865
66.8k53865
asked Nov 11 at 19:12
Floroz
85
85
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
up vote
0
down vote
accepted
I understand from the kata that letters are to be separated by one space and words by three spaces.
As a first step I will two changes to the hash morse_dict
: remove the key ' '
; and add key-value pairs for some punctuation characters. The space character key is not needed; the need for punctuation codes is discussed in the kata.
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"=>"-----", "."=>".-.-.-", ","=>"--..--", "?"=>"..--..",
# "!"=>"-.-.--"}
I obtained the Morse codes for the punctuation characters from the Morse Code Wiki. Additional punctuation characters could be added if desired.
The hash ALPHA_TO_MORSE
is used in encoding text. The inverse of this hash is needed for decoding messages in Morse code. Also needed for decoding is the key value pair "...---..."=>"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"}
One more hash is needed to deal with cases where the message "sos"
(or "SOS"
--Morse code is case insensitive), or "sos"
followed by a punctuation character (e.g., "sos!"
) is to be encoded.1 See the Wiki.
SOS_WITH_PUNCTUATION = PUNCTUATION.each_with_object({}) { |(k,v),h|
h["sos#{k}"] = "...---... #{v}" }.merge('sos'=>"...---...")
#=> {"sos."=>"...---... .-.-.-", "sos,"=>"...---... --..--",
# "sos?"=>"...---... ..--..", "sos!"=>"...---... -.-.--", "sos"=>"...---..."}
The encoding and decoding methods follow. encode
checks to see if each word in the string is a key in the hash SOS_WITH_PUNCTUATION
. If it is, the value of key is the Morse code for the word; else, the word is divided into letters and each letter is translated into Morse code.
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
We can now try out these two methods.
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 It would be simpler to have a pre-processing step that would convert, say, "sos."
to "sos ."
, but when the resulting Morse code were decoded there would be a space between "sos"
and "."
. I suppose that cryptographers could deal with that, but I've chosen to avoid the insertion of the space.
Manipulate the string directly works, however I receive this errorrb:60:in block in describe: Expected: "SOS", instead got: nil (Test::Error)
I have added SOS to the dictionary and paired with '...---..." but it still returnsnil
– Floroz
Nov 12 at 11:36
What is not clear in "dividing into an array" is: you.split
your stringmorse
into an array of single morseword
, then iterate over the singleword
, then I don't understand exactly the next iteration when you.join
the value of MORSE_TO_ALPHA.
– Floroz
Nov 12 at 11:43
Floors, I apologize for not replying to your comments earlier. I somehow missed them. It’s late now so I’ll look into the problems you mention tomorrow.
– Cary Swoveland
Nov 13 at 9:19
Thank you Cary, I have actually managed to get past the issue by inserting the "SOS" in the dictionary manually and added an if statement just to ensure I could pass the test, and incurred in another error using the different versions of your code as it does not encode back the punctuation (".,!?").
– Floroz
Nov 13 at 14:12
Floroz, I've edited my answer.
– Cary Swoveland
Nov 15 at 4:34
add a comment |
up vote
1
down vote
Using Hash#key without replacing the array, rather creating a new one (use map!
for replacement):
array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
array.map { |el| hash.key(el) }
# => [nil, nil, :c, :a, nil]
You may want to think about using Hash#invert and simply referencing the elements by keys for performance reasons as Hash#key
is O(n)
while Hash#
is O(1)
.
array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
inverted_hash = hash.invert
array.map { |el| inverted_hash[el] }
# => [nil, nil, :c, :a, nil]
add a comment |
up vote
0
down vote
assuming: arr = 'a b c d'
, which is not an arr, so please make that morse_string
def morse_code(morse_string)
new_elements =
# iterate over each character in the string,
morse_string.split(" ").each do |element|
if morse_dict[element]
# https://apidock.com/ruby/Array/push
new_elements.push( morse_dict[element] )
else
# whatever you want to do when there is no match
end
end
# re-create the string again, but with braille
# https://apidock.com/ruby/Array/join
new_elements.join(' ')
end
morse_string = 'a b c d'
morse_code(morse_string)
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
I understand from the kata that letters are to be separated by one space and words by three spaces.
As a first step I will two changes to the hash morse_dict
: remove the key ' '
; and add key-value pairs for some punctuation characters. The space character key is not needed; the need for punctuation codes is discussed in the kata.
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"=>"-----", "."=>".-.-.-", ","=>"--..--", "?"=>"..--..",
# "!"=>"-.-.--"}
I obtained the Morse codes for the punctuation characters from the Morse Code Wiki. Additional punctuation characters could be added if desired.
The hash ALPHA_TO_MORSE
is used in encoding text. The inverse of this hash is needed for decoding messages in Morse code. Also needed for decoding is the key value pair "...---..."=>"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"}
One more hash is needed to deal with cases where the message "sos"
(or "SOS"
--Morse code is case insensitive), or "sos"
followed by a punctuation character (e.g., "sos!"
) is to be encoded.1 See the Wiki.
SOS_WITH_PUNCTUATION = PUNCTUATION.each_with_object({}) { |(k,v),h|
h["sos#{k}"] = "...---... #{v}" }.merge('sos'=>"...---...")
#=> {"sos."=>"...---... .-.-.-", "sos,"=>"...---... --..--",
# "sos?"=>"...---... ..--..", "sos!"=>"...---... -.-.--", "sos"=>"...---..."}
The encoding and decoding methods follow. encode
checks to see if each word in the string is a key in the hash SOS_WITH_PUNCTUATION
. If it is, the value of key is the Morse code for the word; else, the word is divided into letters and each letter is translated into Morse code.
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
We can now try out these two methods.
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 It would be simpler to have a pre-processing step that would convert, say, "sos."
to "sos ."
, but when the resulting Morse code were decoded there would be a space between "sos"
and "."
. I suppose that cryptographers could deal with that, but I've chosen to avoid the insertion of the space.
Manipulate the string directly works, however I receive this errorrb:60:in block in describe: Expected: "SOS", instead got: nil (Test::Error)
I have added SOS to the dictionary and paired with '...---..." but it still returnsnil
– Floroz
Nov 12 at 11:36
What is not clear in "dividing into an array" is: you.split
your stringmorse
into an array of single morseword
, then iterate over the singleword
, then I don't understand exactly the next iteration when you.join
the value of MORSE_TO_ALPHA.
– Floroz
Nov 12 at 11:43
Floors, I apologize for not replying to your comments earlier. I somehow missed them. It’s late now so I’ll look into the problems you mention tomorrow.
– Cary Swoveland
Nov 13 at 9:19
Thank you Cary, I have actually managed to get past the issue by inserting the "SOS" in the dictionary manually and added an if statement just to ensure I could pass the test, and incurred in another error using the different versions of your code as it does not encode back the punctuation (".,!?").
– Floroz
Nov 13 at 14:12
Floroz, I've edited my answer.
– Cary Swoveland
Nov 15 at 4:34
add a comment |
up vote
0
down vote
accepted
I understand from the kata that letters are to be separated by one space and words by three spaces.
As a first step I will two changes to the hash morse_dict
: remove the key ' '
; and add key-value pairs for some punctuation characters. The space character key is not needed; the need for punctuation codes is discussed in the kata.
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"=>"-----", "."=>".-.-.-", ","=>"--..--", "?"=>"..--..",
# "!"=>"-.-.--"}
I obtained the Morse codes for the punctuation characters from the Morse Code Wiki. Additional punctuation characters could be added if desired.
The hash ALPHA_TO_MORSE
is used in encoding text. The inverse of this hash is needed for decoding messages in Morse code. Also needed for decoding is the key value pair "...---..."=>"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"}
One more hash is needed to deal with cases where the message "sos"
(or "SOS"
--Morse code is case insensitive), or "sos"
followed by a punctuation character (e.g., "sos!"
) is to be encoded.1 See the Wiki.
SOS_WITH_PUNCTUATION = PUNCTUATION.each_with_object({}) { |(k,v),h|
h["sos#{k}"] = "...---... #{v}" }.merge('sos'=>"...---...")
#=> {"sos."=>"...---... .-.-.-", "sos,"=>"...---... --..--",
# "sos?"=>"...---... ..--..", "sos!"=>"...---... -.-.--", "sos"=>"...---..."}
The encoding and decoding methods follow. encode
checks to see if each word in the string is a key in the hash SOS_WITH_PUNCTUATION
. If it is, the value of key is the Morse code for the word; else, the word is divided into letters and each letter is translated into Morse code.
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
We can now try out these two methods.
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 It would be simpler to have a pre-processing step that would convert, say, "sos."
to "sos ."
, but when the resulting Morse code were decoded there would be a space between "sos"
and "."
. I suppose that cryptographers could deal with that, but I've chosen to avoid the insertion of the space.
Manipulate the string directly works, however I receive this errorrb:60:in block in describe: Expected: "SOS", instead got: nil (Test::Error)
I have added SOS to the dictionary and paired with '...---..." but it still returnsnil
– Floroz
Nov 12 at 11:36
What is not clear in "dividing into an array" is: you.split
your stringmorse
into an array of single morseword
, then iterate over the singleword
, then I don't understand exactly the next iteration when you.join
the value of MORSE_TO_ALPHA.
– Floroz
Nov 12 at 11:43
Floors, I apologize for not replying to your comments earlier. I somehow missed them. It’s late now so I’ll look into the problems you mention tomorrow.
– Cary Swoveland
Nov 13 at 9:19
Thank you Cary, I have actually managed to get past the issue by inserting the "SOS" in the dictionary manually and added an if statement just to ensure I could pass the test, and incurred in another error using the different versions of your code as it does not encode back the punctuation (".,!?").
– Floroz
Nov 13 at 14:12
Floroz, I've edited my answer.
– Cary Swoveland
Nov 15 at 4:34
add a comment |
up vote
0
down vote
accepted
up vote
0
down vote
accepted
I understand from the kata that letters are to be separated by one space and words by three spaces.
As a first step I will two changes to the hash morse_dict
: remove the key ' '
; and add key-value pairs for some punctuation characters. The space character key is not needed; the need for punctuation codes is discussed in the kata.
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"=>"-----", "."=>".-.-.-", ","=>"--..--", "?"=>"..--..",
# "!"=>"-.-.--"}
I obtained the Morse codes for the punctuation characters from the Morse Code Wiki. Additional punctuation characters could be added if desired.
The hash ALPHA_TO_MORSE
is used in encoding text. The inverse of this hash is needed for decoding messages in Morse code. Also needed for decoding is the key value pair "...---..."=>"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"}
One more hash is needed to deal with cases where the message "sos"
(or "SOS"
--Morse code is case insensitive), or "sos"
followed by a punctuation character (e.g., "sos!"
) is to be encoded.1 See the Wiki.
SOS_WITH_PUNCTUATION = PUNCTUATION.each_with_object({}) { |(k,v),h|
h["sos#{k}"] = "...---... #{v}" }.merge('sos'=>"...---...")
#=> {"sos."=>"...---... .-.-.-", "sos,"=>"...---... --..--",
# "sos?"=>"...---... ..--..", "sos!"=>"...---... -.-.--", "sos"=>"...---..."}
The encoding and decoding methods follow. encode
checks to see if each word in the string is a key in the hash SOS_WITH_PUNCTUATION
. If it is, the value of key is the Morse code for the word; else, the word is divided into letters and each letter is translated into Morse code.
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
We can now try out these two methods.
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 It would be simpler to have a pre-processing step that would convert, say, "sos."
to "sos ."
, but when the resulting Morse code were decoded there would be a space between "sos"
and "."
. I suppose that cryptographers could deal with that, but I've chosen to avoid the insertion of the space.
I understand from the kata that letters are to be separated by one space and words by three spaces.
As a first step I will two changes to the hash morse_dict
: remove the key ' '
; and add key-value pairs for some punctuation characters. The space character key is not needed; the need for punctuation codes is discussed in the kata.
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"=>"-----", "."=>".-.-.-", ","=>"--..--", "?"=>"..--..",
# "!"=>"-.-.--"}
I obtained the Morse codes for the punctuation characters from the Morse Code Wiki. Additional punctuation characters could be added if desired.
The hash ALPHA_TO_MORSE
is used in encoding text. The inverse of this hash is needed for decoding messages in Morse code. Also needed for decoding is the key value pair "...---..."=>"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"}
One more hash is needed to deal with cases where the message "sos"
(or "SOS"
--Morse code is case insensitive), or "sos"
followed by a punctuation character (e.g., "sos!"
) is to be encoded.1 See the Wiki.
SOS_WITH_PUNCTUATION = PUNCTUATION.each_with_object({}) { |(k,v),h|
h["sos#{k}"] = "...---... #{v}" }.merge('sos'=>"...---...")
#=> {"sos."=>"...---... .-.-.-", "sos,"=>"...---... --..--",
# "sos?"=>"...---... ..--..", "sos!"=>"...---... -.-.--", "sos"=>"...---..."}
The encoding and decoding methods follow. encode
checks to see if each word in the string is a key in the hash SOS_WITH_PUNCTUATION
. If it is, the value of key is the Morse code for the word; else, the word is divided into letters and each letter is translated into Morse code.
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
We can now try out these two methods.
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 It would be simpler to have a pre-processing step that would convert, say, "sos."
to "sos ."
, but when the resulting Morse code were decoded there would be a space between "sos"
and "."
. I suppose that cryptographers could deal with that, but I've chosen to avoid the insertion of the space.
edited Nov 15 at 4:39
answered Nov 11 at 22:16
Cary Swoveland
66.8k53865
66.8k53865
Manipulate the string directly works, however I receive this errorrb:60:in block in describe: Expected: "SOS", instead got: nil (Test::Error)
I have added SOS to the dictionary and paired with '...---..." but it still returnsnil
– Floroz
Nov 12 at 11:36
What is not clear in "dividing into an array" is: you.split
your stringmorse
into an array of single morseword
, then iterate over the singleword
, then I don't understand exactly the next iteration when you.join
the value of MORSE_TO_ALPHA.
– Floroz
Nov 12 at 11:43
Floors, I apologize for not replying to your comments earlier. I somehow missed them. It’s late now so I’ll look into the problems you mention tomorrow.
– Cary Swoveland
Nov 13 at 9:19
Thank you Cary, I have actually managed to get past the issue by inserting the "SOS" in the dictionary manually and added an if statement just to ensure I could pass the test, and incurred in another error using the different versions of your code as it does not encode back the punctuation (".,!?").
– Floroz
Nov 13 at 14:12
Floroz, I've edited my answer.
– Cary Swoveland
Nov 15 at 4:34
add a comment |
Manipulate the string directly works, however I receive this errorrb:60:in block in describe: Expected: "SOS", instead got: nil (Test::Error)
I have added SOS to the dictionary and paired with '...---..." but it still returnsnil
– Floroz
Nov 12 at 11:36
What is not clear in "dividing into an array" is: you.split
your stringmorse
into an array of single morseword
, then iterate over the singleword
, then I don't understand exactly the next iteration when you.join
the value of MORSE_TO_ALPHA.
– Floroz
Nov 12 at 11:43
Floors, I apologize for not replying to your comments earlier. I somehow missed them. It’s late now so I’ll look into the problems you mention tomorrow.
– Cary Swoveland
Nov 13 at 9:19
Thank you Cary, I have actually managed to get past the issue by inserting the "SOS" in the dictionary manually and added an if statement just to ensure I could pass the test, and incurred in another error using the different versions of your code as it does not encode back the punctuation (".,!?").
– Floroz
Nov 13 at 14:12
Floroz, I've edited my answer.
– Cary Swoveland
Nov 15 at 4:34
Manipulate the string directly works, however I receive this error
rb:60:in block in describe: Expected: "SOS", instead got: nil (Test::Error)
I have added SOS to the dictionary and paired with '...---..." but it still returns nil
– Floroz
Nov 12 at 11:36
Manipulate the string directly works, however I receive this error
rb:60:in block in describe: Expected: "SOS", instead got: nil (Test::Error)
I have added SOS to the dictionary and paired with '...---..." but it still returns nil
– Floroz
Nov 12 at 11:36
What is not clear in "dividing into an array" is: you
.split
your string morse
into an array of single morse word
, then iterate over the single word
, then I don't understand exactly the next iteration when you .join
the value of MORSE_TO_ALPHA.– Floroz
Nov 12 at 11:43
What is not clear in "dividing into an array" is: you
.split
your string morse
into an array of single morse word
, then iterate over the single word
, then I don't understand exactly the next iteration when you .join
the value of MORSE_TO_ALPHA.– Floroz
Nov 12 at 11:43
Floors, I apologize for not replying to your comments earlier. I somehow missed them. It’s late now so I’ll look into the problems you mention tomorrow.
– Cary Swoveland
Nov 13 at 9:19
Floors, I apologize for not replying to your comments earlier. I somehow missed them. It’s late now so I’ll look into the problems you mention tomorrow.
– Cary Swoveland
Nov 13 at 9:19
Thank you Cary, I have actually managed to get past the issue by inserting the "SOS" in the dictionary manually and added an if statement just to ensure I could pass the test, and incurred in another error using the different versions of your code as it does not encode back the punctuation (".,!?").
– Floroz
Nov 13 at 14:12
Thank you Cary, I have actually managed to get past the issue by inserting the "SOS" in the dictionary manually and added an if statement just to ensure I could pass the test, and incurred in another error using the different versions of your code as it does not encode back the punctuation (".,!?").
– Floroz
Nov 13 at 14:12
Floroz, I've edited my answer.
– Cary Swoveland
Nov 15 at 4:34
Floroz, I've edited my answer.
– Cary Swoveland
Nov 15 at 4:34
add a comment |
up vote
1
down vote
Using Hash#key without replacing the array, rather creating a new one (use map!
for replacement):
array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
array.map { |el| hash.key(el) }
# => [nil, nil, :c, :a, nil]
You may want to think about using Hash#invert and simply referencing the elements by keys for performance reasons as Hash#key
is O(n)
while Hash#
is O(1)
.
array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
inverted_hash = hash.invert
array.map { |el| inverted_hash[el] }
# => [nil, nil, :c, :a, nil]
add a comment |
up vote
1
down vote
Using Hash#key without replacing the array, rather creating a new one (use map!
for replacement):
array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
array.map { |el| hash.key(el) }
# => [nil, nil, :c, :a, nil]
You may want to think about using Hash#invert and simply referencing the elements by keys for performance reasons as Hash#key
is O(n)
while Hash#
is O(1)
.
array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
inverted_hash = hash.invert
array.map { |el| inverted_hash[el] }
# => [nil, nil, :c, :a, nil]
add a comment |
up vote
1
down vote
up vote
1
down vote
Using Hash#key without replacing the array, rather creating a new one (use map!
for replacement):
array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
array.map { |el| hash.key(el) }
# => [nil, nil, :c, :a, nil]
You may want to think about using Hash#invert and simply referencing the elements by keys for performance reasons as Hash#key
is O(n)
while Hash#
is O(1)
.
array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
inverted_hash = hash.invert
array.map { |el| inverted_hash[el] }
# => [nil, nil, :c, :a, nil]
Using Hash#key without replacing the array, rather creating a new one (use map!
for replacement):
array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
array.map { |el| hash.key(el) }
# => [nil, nil, :c, :a, nil]
You may want to think about using Hash#invert and simply referencing the elements by keys for performance reasons as Hash#key
is O(n)
while Hash#
is O(1)
.
array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
inverted_hash = hash.invert
array.map { |el| inverted_hash[el] }
# => [nil, nil, :c, :a, nil]
edited Nov 11 at 20:06
answered Nov 11 at 19:23
Marcin Kołodziej
4,067315
4,067315
add a comment |
add a comment |
up vote
0
down vote
assuming: arr = 'a b c d'
, which is not an arr, so please make that morse_string
def morse_code(morse_string)
new_elements =
# iterate over each character in the string,
morse_string.split(" ").each do |element|
if morse_dict[element]
# https://apidock.com/ruby/Array/push
new_elements.push( morse_dict[element] )
else
# whatever you want to do when there is no match
end
end
# re-create the string again, but with braille
# https://apidock.com/ruby/Array/join
new_elements.join(' ')
end
morse_string = 'a b c d'
morse_code(morse_string)
add a comment |
up vote
0
down vote
assuming: arr = 'a b c d'
, which is not an arr, so please make that morse_string
def morse_code(morse_string)
new_elements =
# iterate over each character in the string,
morse_string.split(" ").each do |element|
if morse_dict[element]
# https://apidock.com/ruby/Array/push
new_elements.push( morse_dict[element] )
else
# whatever you want to do when there is no match
end
end
# re-create the string again, but with braille
# https://apidock.com/ruby/Array/join
new_elements.join(' ')
end
morse_string = 'a b c d'
morse_code(morse_string)
add a comment |
up vote
0
down vote
up vote
0
down vote
assuming: arr = 'a b c d'
, which is not an arr, so please make that morse_string
def morse_code(morse_string)
new_elements =
# iterate over each character in the string,
morse_string.split(" ").each do |element|
if morse_dict[element]
# https://apidock.com/ruby/Array/push
new_elements.push( morse_dict[element] )
else
# whatever you want to do when there is no match
end
end
# re-create the string again, but with braille
# https://apidock.com/ruby/Array/join
new_elements.join(' ')
end
morse_string = 'a b c d'
morse_code(morse_string)
assuming: arr = 'a b c d'
, which is not an arr, so please make that morse_string
def morse_code(morse_string)
new_elements =
# iterate over each character in the string,
morse_string.split(" ").each do |element|
if morse_dict[element]
# https://apidock.com/ruby/Array/push
new_elements.push( morse_dict[element] )
else
# whatever you want to do when there is no match
end
end
# re-create the string again, but with braille
# https://apidock.com/ruby/Array/join
new_elements.join(' ')
end
morse_string = 'a b c d'
morse_code(morse_string)
answered Nov 11 at 19:36
awsmsce
788
788
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53252238%2fruby-iterating-over-an-array-and-find-match-in-an-hash-and-replace-the-element-i%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown