So I'm doing a question where the function counts repeating characters and prints them out. I do get the right solution, but what ends up happening is that the letter a doesn't get counted since it showed up before.
So here's the code
fun sCompression(s: String): String{
var solution = ""
var count = 1
for (i in 0 until s.length - 1){
if (s[i] == s[i 1]){
count
}else{
solution = solution.plus("${s[i]}$count")
count = 1
}
}
return solution
}
Here are the inputs
And There Outputs
Expected output
Out1:a2b3c6a5
Out2:a1c1a1c1b1a4
Out3:a2b3c6d11u6x2
P.S. as you can see, the x in the last input also doesn't show up either. Any help will be appreciated, thanks
CodePudding user response:
Right now, you are appending a new run length encoding ${s[i]}$count"
only when s[i] != s[i 1]
. Notice that this condition is never true for the last "segment' of the same characters.
Consider a string with 3 "segments" with the same characters. I have annotated the positions of the index i
where the condition s[i] != s[i 1]
would be true:
aaaaabbbbbbccccccc
^ ^
There are only 2 locations, in a string with 3 "segments"! In the first location, you append "a5", and in the second location, you append "b6", and that's it.
Basically, you need to also handle the last "segment" of the string. When you reach the end of the loop, you would have already counted the length of this segment using the variable count
. All you need to do is to append to solution
.
// after the loop:
val last = s.lastOrNull()
if (last != null) { // to handle the case of empty strings
solution = "${last}$count" // you can use " =", no need to call .plus
}
You can also do this with a string builder, which can be more efficient:
fun sCompression(s: String) = buildString {
var count = 1
for (i in 0 until s.length - 1){
if (s[i] == s[i 1]){
count
}else{
append("${s[i]}$count")
count = 1
}
}
val last = s.lastOrNull()
if (last != null) {
append("${last}$count")
}
}