BBK#6: The Morse Code 🀫

problemsolving Dec 28, 2020

Don't be a Java-ish dev in 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 alot!

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

This quiz was suggested by Rohan Singh (@zaraki596) on Twitter, sorry for the delay mate! 
Kotlin Weekly #231
Issue 32

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..

val morseCode = "-.-- --- ..-   .... .- ...- .   .-   -... .. --.   -... .-. .- .. -.   ..-. --- .-.   -.- --- - .-.. .. -."

// write a function that converts this MorseCode to English
fun decodeMorse(morseCode:String):String{
   // .. do stuff
}

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 "="
)

Try it put yourself :
πŸ‘¨πŸ»β€πŸ’»πŸ‘‰ Β https://www.codewars.com/kata/54b724efac3d5402db00065e/train/kotlin



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

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.πŸ’‘
Accumulator Pattern for beginners | Fold vs Reduce | AndroidBites
Accumulator pattern in kotlin | kotlin how to reduce | kotlin how to fold | reduce vs fold | best practice to reduce | transformation in kotlin | collection transformation | java vs koltin | java for loop anti patterns


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

Performance hit in here 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 advance use cases πŸ’‘
Snippets | List to String with Examples | Androidbites
kotlin string | kotlin variable in string | kotlin join strings with delimiter | kotlin map to string | kotlin string interpolation | kotlin string collection join | list to string and string to list kotlin | kotlin string format


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 - Kotlin Programming Language
checkout docs to learn more about 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!



Solution 4:

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


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

Don't get attached to a solution!



Conclusion

Aim of these articles is not hate on Java, but to help people learn various ways in which they can write 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 Previous:

BigBrainKotlin - Among us
Don’t be a Java-ish dev in 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!

Solve Next :

BigBrainKotlin - Equal Sides 🀝
Don’t be a Java-ish dev in Kotlin-ish world, Morse code decode! let do it in Kotlinish way

Enjoy the Post?

a clap is much appreciated if you enjoyed. No sign up or cost associated :)




Chetan gupta

Hi there! call me Ch8n, I'm a mobile technology enthusiast! love Android #kotlinAlltheWay, CodingMantra: #cleanCoder #TDD #SOLID #designpatterns

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.