Rabbit Hole: Morse Code
About this time last year I taught a CodeCamp for Comcast. It included Node, HTML, CSS, DOM, Angular, Java, Springboot, SQL, and Hibernate.
When teaching that class I put together a morse code to english (and vice versa) encoding decoding project as a demo for my students. It originally lived completely on repl.it, but I just moved it to GitHub:
It wasn’t focused on functional programming at all and was really just demonstrating programming fundamentals in JavaScript. After looking over the source code it looks like I snuck a couple of .map()
methods in there!
I think I will rebuild it in Scala
as it compliments the challenge I just completed.
New Project
I created a hello-world project earlier with sbt
. It didn’t have maven, but I don’t think this project will need anything outside of Scala’s standard library so I’ll just create it with sbt
.
sbt new scala/scala3.g8
And then entered morse-code
which created a new Scala 3 project directory in my home directory.
According to the Scala docs I can simply open the created build.sbt
as a project in IntelliJ and it will configure the rest.
First HashMap
Using the same syntax from the previous example I created:
import scala.collection.immutable.HashMap
@main def hello: Unit =
println(morseCodeToLetter)
val morseCodeToLetter: Map[String, String] = HashMap[String, String] (
".-" -> "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",
"-----" -> "0",
".----" -> "1",
"..---" -> "2",
"...--" -> "3",
"....-" -> "4",
"....." -> "5",
"-...." -> "6",
"--..." -> "7",
"---.." -> "8",
"----." -> "9",
".-.-.-" -> ".",
"--..--" -> ",",
"..--.." -> "?",
"-.-.--" -> "!",
"...---..." -> "sos",
)
And got this output:
HashMap(. -> e, .... -> h, --. -> g, .-. -> r, -.... -> 6, --- -> o, .--. -> p, ..--.. -> ?, -.-. -> c, --.- -> q, ..-. -> f, .-- -> w, ---.. -> 8, ..- -> u, -. -> n, ----- -> 0, --..-- -> ,, -..- -> x, .---- -> 1, ...- -> v, - -> t, .- -> a, ....- -> 4, -.. -> d, .. -> i, -.-- -> y, --.. -> z, ...-- -> 3, ... -> s, ..... -> 5, ----. -> 9, -- -> m, .-.-.- -> ., ..--- -> 2, ...---... -> sos, -.- -> k, .-.. -> l, .--- -> j, -... -> b, --... -> 7, -.-.-- -> !)
Second HashMap
Using the .map()
method I should be able to easily reverse the keys and values to create a new HashMap in one concise line:
val letterToMorseCode: Map[String, String] = morseCodeToLetter.map((key, value) => value -> key)
And print it out as well in the main method:
@main def hello: Unit =
println(letterToMorseCode)
Output:
HashMap(e -> ., 8 -> ---.., t -> -, ! -> -.-.--, a -> .-, 5 -> ....., m -> --, i -> .., p -> .--., 2 -> ..---, w -> .--, 3 -> ...--, k -> -.-, s -> ..., x -> -..-, 4 -> ....-, n -> -., . -> .-.-.-, 9 -> ----., j -> .---, y -> -.--, u -> ..-, f -> ..-., , -> --..--, v -> ...-, 6 -> -...., 1 -> .----, q -> --.-, b -> -..., g -> --., l -> .-.., 0 -> -----, ? -> ..--.., sos -> ...---..., c -> -.-., h -> ...., 7 -> --..., r -> .-., o -> ---, z -> --.., d -> -..)
Well that just worked like a charm.
Testing (manually) it Out
I changed the main method to:
// paul should be: .--. .- ..- .-..
println("paul".split("").map(letterToMorseCode.getOrElse(_, "ERROR")).mkString(" "))
// dog should be: -.. --- --.
println("dog".split("").map(letterToMorseCode.getOrElse(_, "ERROR")).mkString(" "))
// sos should be: ... --- ...
println("sos".split("").map(letterToMorseCode.getOrElse(_, "ERROR")).mkString(" "))
// .--. .- ..- .-.. should be: paul
println(".--. .- ..- .-..".split(" ").map(morseCodeToLetter.getOrElse(_, "ERROR")).mkString)
// -.. --- --. should be: dog
println("-.. --- --.".split(" ").map(morseCodeToLetter.getOrElse(_, "ERROR")).mkString)
// ... --- ... should be: sos
println("... --- ...".split(" ").map(morseCodeToLetter.getOrElse(_, "ERROR")).mkString)
And got this output:
.--. .- ..- .-..
-.. --- --.
... --- ...
paul
dog
sos
Very nice. If I was more comfortable with Scala, I would have written unit tests. But that will come with more time in the language.
GitHub Repo
Take a look at the scala-morse-code GitHub repo to see the full code.