Do map of Pairs with String

Hello There is a problem. You are given a string, you need to create a map of pairs where the first element is a letter (enchantment), the second is the number of consecutive letters. For example, for the word “hello” there will be such a map [(h,1), (e, 1), (l, 2), (o, 1)]. How to write it with a little code? Maybe I should somehow use groupBy{} ?

This sounds like a programming exercise so I wont give you the answer in code. I will still try to help you though:
groupBy won’t work since it does not take the order of the letters into account. What you want to do is iterate over the letters of the string and keep track of the current letter and the number of times it occurred. Every time you find a new letter you add the data to your result.


What should the result be for a string like “aabaaac”? It’s not clear to me from your description? Should it be [(a, 5), (b, 1), (c, 1)] or [(a, 2), (b, 1), (c, 1)] or [(a, 3), (b, 1), (c, 1)]. If it’s the first you can ignore what I said above and use groupBy and then just count the elements of each group.
It also could be [(a, 2), (b, 1), (a, 3), (c, 1)], in that case you won’t be able to use a map as the result data structure and you will have to use a List<Pair<Char, Int>> instead.

It could be [(a, 2), (b, 1), (a, 3), (c, 1)]. I know how to realize that using List<Pair<Char, Int>>
My code below:

fun main() {


    var s = readLine()!!

    var list1 = mutableListOf<Pair<Char, Int>>()

    var startIndex = 0
    var endIndex = 0

    while (endIndex <= s.length - 1){
        while(endIndex != s.length - 1 && s[endIndex] == s[endIndex + 1]){
            ++endIndex
        }

        list1.add(Pair(s[endIndex], endIndex - startIndex + 1))

        ++endIndex
        startIndex = endIndex
    }


    println(list1)
}

But I want to make my code shorter. Can you help me with it?

Take a look to Kotlin standard library, I strongly suggest you Kotlin Koans.

I left a simple implementation uncommented, good luck :wink:

fun main() {
    val string = "hello"
    val pairs =
            (0 until string.length)
                    .filter { it == 0 || string[it - 1] != string[it] }
                    .map { string.substring(it) }
                    .map { s -> s[0] to s.takeWhile { s[0] == it }.length }
    println(pairs)
}
1 Like

Thank you!

Wow. This seems awfully complex, but I guess it’s correct. I would have used a simple loop like the OP.
Maybe

//sampleStart
fun genPairs(s: String): List<Pair<Char, Int>> {
    if(s.isEmpty()) return emptyList()
    var current = s[0]
    var count = 0
    val pairs = mutableListOf<Pair<Char, Int>>()
    for(c in s) {
        if(c == current) count++
        else {
            pairs.add(current to count)
            current = c
            count = 1
        }
    }
    pairs.add(current to count)
    return pairs
}
//sampleEnd
fun main() {
   genPairs("Hello").forEach { println(it) }
}

Late to this thread, but in case anyone else happens to come across this.

Could do something like this:

val word = "hello"

var letterCount = word.toList()
    .distinct()
    .map { letter -> letter to word.count { it == letter } }
            
println(letterCount)