Solving Merge Two String Alternately using Kotlin....
# feed
c
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
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
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
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
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
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
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
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