what kind of optimizations could i do to this func...
# announcements
s
what kind of optimizations could i do to this function?
Copy code
const val LOWER_CASE_LETTERS = "abcdefghijklmnopqrstuvwxyz"
const val UPPER_CASE_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

fun rotateLetter(input: Char, rotations: Int): Char {
    val isUpperCase = input in UPPER_CASE_LETTERS
    val isLowerCase = input in LOWER_CASE_LETTERS
    var variableRotations = rotations
    var variableInput = input

    while (variableRotations != 0) {
        when {
            isUpperCase -> {
                if (variableInput.toInt() == 90) variableInput = 'A'
                else variableInput += 1
            }
            isLowerCase -> {
                if (variableInput.toInt() == 122) variableInput = 'a'
                else variableInput += 1
            }
            else -> return input
        }
        variableRotations--
    }
    return variableInput
}
n
I mean, off the bat, a well known optimization for checking if something is upper case or lower case is to subtract A/a and check if the result is in the range 0-25
Another thing that's not so great here is that you are branching on the same thing repeatedly in a loop. I don't know if Kotlin is going to be clever enough to do a branch pullout here, probably not
s
could u explain the first point again?
m
Copy code
val isUpperCase = input in 'A' .. 'Z'
e
Copy code
val isUpperCase = input in 'A'..'Z'
Kotlin will optimize it to 2 comparisons. your current
in
check requires 26 comparisons
l
Do you even need a loop? Looks to me that you can do
input.toInt() + rotations
and then, depending on
if (input.isUppercase())
you can subtract 90 or 122 if needed
m
The values of
when
are constant within the loop. I’d use
while
inside
when
, not the other way round. Or is it a bug and you want
isUpperCase = …
meant to be in the
while
loop?
n
I don't know how kotlin optimizations work but you can get it down to a single comparison in C
but that's probably pretty low level for kotlin
e
it's not a single comparison in C if chars are signed, which varies... (although of course it can be cast)
n
yeah, you can turn range comparisons on signed into a single unsigned comparison
e
in any case,
Copy code
if (input in 'A'..'Z' || input in 'a'..'z') {
    val codePoint = input.toInt()
    (codePoint and 0x1F.inv() or (codePoint.and(0x1F) - 1 + rotations) % 26 + 1).toChar()
} else {
    input
}
👀 1
as @Luke says, no loops required
👍 1
s
I understood p much nothing of that code
but i am trying
l
That's low level bit manipulation, which is understandably hard to read. I don't suggest trying to start coding by understanding that. I would start your problem by checking if the input is outside your valid inputs and return early if it is. Then you add
rotations
to your char, and if you busted z/Z, you subtract to return to a valid output, and you return the result.
r
Not to barrage you with data, but if you watch this video, you’ll be able to decipher ephemient’s code:

https://www.youtube.com/watch?v=T_p22jMZSrk

s
thanks a lot @Luke
e
ASCII is laid out such that A = 64 + 1, B = 64 + 2, ... Z = 64 + 26; a = 96 + 1, b = 96 + 2, ... z = 96 + 26
it and 0x1F.inv()
turns A..Z into 64 and a..z into 96
(it and 0x1F) - 1
turns A..Z, a..z into 0-25
((it and 0x1F) - 1 + rotations) % 26
turns A..Z, a..z into 0-25, rotated
it and 0x1F.inv() or (((it and 0x1F) - 1 + rotations) % 26 + 1)
combines them back to the expected ASCII