DEV Community

Cover image for BBK#5: The Morse Code πŸ€«
Chetan garg
Chetan garg

Posted on β€’ Originally published at chetangupta.net

2 2

BBK#5: The Morse Code πŸ€«

Don't be a Java-ish dev in a Kotlin-ish world, improve your knowledge about Koltin Standard Library and write better Kotlin code. ✌🏻 If your Java dev migrating to Kotlin this will help you learn a lot!

I have a secret code for you to crack detective! πŸ•΅οΈβ€β™€οΈ

originally published on https://chetangupta.net/bbk-main/

This quiz was suggested by Rohan Singh on Twitter, sorry for the delay mate!

Question: You have received a secret message! unfortunately, you can't just read it, it is encoded in Morse code. Your task is to implement a function that would take the morse code as input and return a human-readable string. 3 spaces are used to separate words and
Extra spaces before or after the code have no meaning and should be ignored.

Message : -.β€Š-β€Š-β€Š-β€Š..- β€¦. .- β€¦- . .- -… ..β€Š-β€Š. -… .-. .- .. -. ..-.β€Š-β€Š- .-. -.-β€Š-β€Š-β€Š-β€Š.-.. .. -.
val morseCode = "-.-- --- ..-   .... .- ...- .   .-   -... .. --.   -... .-. .- .. -.   ..-. --- .-.   -.- --- - .-.. .. -."  
// write a function that converts this MorseCode to English fun decodeMorse(morseCode:String):String{   
 // .. do stuff 
}
Enter fullscreen mode Exit fullscreen mode

Given Morse Code Decoder

val morseDecoder = mapOf<String, String>(
        ".-" to "A",
        "-..." to "B",
        "-.-." to "C",
        "-.." to "D",
        "." to "E",
        "..-." to "F",
        "--." to "G",
        "...." to "H",
        ".." to "I",
        ".---" to "J",
        "-.-" to "K",
        ".-.." to "L",
        "--" to "M",
        "-." to "N",
        "---" to "O",
        ".--." to "P",
        "--.-" to "Q",
        ".-." to "R",
        "..." to "S",
        "-" to "T",
        "..-" to "U",
        "...-" to "V",
        ".--" to "W",
        "-..-" to "X",
        "-.--" to "Y",
        "--.." to "Z",
        ".----" to "1",
        "..---" to "2",
        "...--" to "3",
        "....-" to "4",
        "....." to "5",
        "-...." to "6",
        "--..." to "7",
        "---.." to "8",
        "----." to "9",
        "-----" to "0",
        "" to " ",
        ".-.-.-" to ".",
        "--..--" to ",",
        "---..." to ".",
        "..--.." to "?",
        "-.-.--" to "!",
        "...---..." to "SOS",
        "-....-" to "''",
        "-..-." to "/",
        "-.--.-" to "()",
        ".--.-." to "@",
        "-...-" to "="
)
Enter fullscreen mode Exit fullscreen mode

Try it put yourself :
πŸ‘¨πŸ»β€πŸ’»πŸ‘‰ Try Yourself

Solution 1:

Same old imperative way. πŸ˜ͺ

fun decodeMorse(code: String): String {
    val morseWords = code.split("   ")
    val humanized = StringBuilder()
    for (morseWord in morseWords) {
        val morseChars = morseWord.split(" ")
        for (morseChar in morseChars) {
            if (morseChar.isNotEmpty()) {
                humanized.append(morseDecoder.get(morseChar))
            }
        }
        humanized.append(" ")
    }
    return humanized.toString()
}
// πŸ‘¨πŸ»β€πŸ”§ complexity : O(n^2)
// ⏱ performance : took 509.0 us on my machine
Enter fullscreen mode Exit fullscreen mode

Btw there is nothing wrong in this way, just the loops make it very expressive, there is no issue of mutations and accidental updates in it. πŸ™ŒπŸ»

Checkout why accumulator pattern in imperative style is bad.πŸ’‘

checkout πŸ‘‰ Accumulator|Fold-Reduce

Solution 2:

Imperative equivalent code in functional style | Stdlib function

fun decodeMorse(code: String): String {
    return code.trim()
        .split("   ")
        .joinToString(separator = " ") { word ->
            word.split(" ")
                    .map { letter -> morseDecoder[letter] ?: "" }
                    .joinToString(separator = "")
        }
}
// πŸ‘¨πŸ»β€πŸ”§ complexity : O(n^2)
// ⏱ performance : took 639.0 us on my machine
Enter fullscreen mode Exit fullscreen mode

The performance hit of there is due to joinToString operation one at the outer loop and multiple times into the inner loop, not good! dood (dude)...☹️

learn joinToString and it's advanced use cases πŸ’‘

checkout πŸ‘‰ list-to-string

Solution 3:

What if we call it once? , if we eliminate the nesting, i.e flatten our words to char?

πŸ‘¨πŸ»β€πŸ’» Let's flatten our List using FlatMap

flatMap

fun decodeMorse(code: String) = code
        .split("  ")
        .flatMap { it.split(" ") }
        .map {morseDecoder.get(it)?:"" }
        .joinToString("")

// πŸ‘¨πŸ»β€πŸ”§ complexity : O(n)
// ⏱ performance : took 464.0 us us on my machine
Whola!
Enter fullscreen mode Exit fullscreen mode

Solution 4:

Or Change the way you are solving this problem πŸ’β€β™€οΈ

fun decodeMorse(code: String): String {
    return code.trim()
        .replace("  ", " ")
        .split(" ")
        .map { morseDecoder[it]?:"" }
        .joinToString(" ")
}
// πŸ‘¨πŸ»β€πŸ”§ complexity : O(n)
// ⏱ performance : took 441.0 us on my machine
Enter fullscreen mode Exit fullscreen mode

Don't get attached to a solution!

Conclusion

The aim of these articles is not hated on Java, but to help people learn various ways in which they can write the same logic better and more Kotlin standard library-focused way.
Hope you find it informative and if you have any feedback or post request or want to subscribe to my mailing list forms are below.

Until next time. Happy Hacking! πŸ‘©β€πŸ’»

Solve many more πŸ‘‡πŸ»

Big-Brain-Kotlin

Image of Timescale

πŸš€ pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applicationsβ€”without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more

Top comments (0)

Sentry growth stunted Image

If you are wasting time trying to track down the cause of a crash, it’s time for a better solution. Get your crash rates to zero (or close to zero as possible) with less time and effort.

Try Sentry for more visibility into crashes, better workflow tools, and customizable alerts and reporting.

Switch Tools πŸ”

πŸ‘‹ Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay