https://kotlinlang.org logo
#feed
Title
# feed
c

Ch8n

10/21/2023, 7:21 AM
Solving Merge Two String Alternately using Kotlin. community submissions are welcome share your Kotlin writing style by solving this problem: https://medium.com/@chetan-garg36/pragmatic-kotlin-merge-two-strings-alternately-benchmarks-a3499433300e
👏 1
s

Sam

10/21/2023, 7:53 AM
This is a nice problem! And I really like the depth you went into when comparing the solutions. I normally don't like coding challenges like this, but for once this one seems like it might at least be vaguely relevant to the real world problems in my actual job. And it's a lot of fun to look for the neatest way to do this in Kotlin. Here's my version—I made it work with a
vararg
just for fun 😄
Copy code
fun mergeAlternately(vararg strings: String): String = buildString {
    val iterators = strings.map { it.iterator() }
    do {
        var shouldContinue = false
        for (iterator in iterators) {
            if (iterator.hasNext()) {
                append(iterator.nextChar())
                shouldContinue = true
            }
        }
    } while (shouldContinue)
}
❤️ 1
It does seem like a shame that
zip
can't be customised to alter the behaviour when the strings are different lengths 😞
c

Ch8n

10/21/2023, 8:01 AM
Thanks sam I will add your submission to the article too for sharing and fun. Definitely or some other operator should have been there for addressing this behaviour
👍 1
s

Sam

10/21/2023, 8:10 AM
I'm sure my version performs worse than your Solution #2 😄. Yours is much better optimised, since it doesn't create so many objects and also allocates the correct capacity for the string builder up front. It's always a challenge to decide whether it's worth the cost of using idioms like iterators.
1
c

Ch8n

10/21/2023, 2:12 PM
thanks for kind words, but I also generally write code keeping readability and maintenance in mind, I measure performance or wait for product requirements to improve app performance then only go and refactor code. Otherwise, it all just drag in productivity.
e

ephemient

10/21/2023, 3:17 PM
don't take this seriously ;)
Copy code
suspend fun mergeAlternately(word1: String, word2: String): String = buildString {
    merge(
        word1.toList().asFlow().onEach { delay(99) },
        word2.toList().asFlow().onEach { delay(100) },
    ).collect(::append)
}
has a chance of working as long as the strings aren't too long
😅 1
😁 1
although to be slightly serious, that is basically delay line sorting, and (stable) sorting does work
Copy code
fun mergeAlternately(word1: String, word2: String): String =
    (word1.withIndex() + word2.withIndex())
        .sortedBy { it.index }
        .joinToString("") { it.value.toString() }
p

Pedro Pereira

10/21/2023, 4:05 PM
This solution also looks good
Copy code
fun mergeAlternately(word1: String, word2: String): String = buildString {
    val minLength = minOf(word1.length, word2.length)
    fun appendRemainder(word: String) {
        for(index in minLength..<word.length)
            append(word[index])
    }
    for(index in 0..<minLength) {
        append(word1[index])
        append(word2[index])
    }
    appendRemainder( if (minLength == word1.length) word2 else word1 )
}
K 1
e

ephemient

10/21/2023, 4:31 PM
there's many solutions but I really prefer the ones where you don't even have to explicitly handle the remainder
Copy code
fun mergeAlternately(word1: String, word2: String): String = buildString {
    repeat(maxOf(word1.length, word2.length)) {
        word1.getOrNull(it)?.let(::append)
        word2.getOrNull(it)?.let(::append)
    }
}
K 2