# Credit card / IMEI check digit in Kotlin

I recently had the need to implement Luhn's Algorithm in a Java/Kotlin application. I needed a function that would add the check digit to the string of a number like a credit card or IMEI. It could be easily modified to check if the last digit is valid.

At first, I had a code of around 20 lines in Java, but by using every Kotlin quirk I could think of, I managed to do it in one line.

fun String.addLastImeiDigit(): String = "$this${10 - this.withIndex().map { if (it.index.and(1) == 0) it.value.toInt() - 48 else (2 * (it.value.toInt() - 48)).run { (this % 10) + (this / 10) } }.sum() % 10}"

Here it is in a more understandable fashion

return "$this${10 - this.withIndex().map {
if (it.index.and(1) == 0) /* if even */
it.value.toInt() - 48 /* ascii to Int */
else
(2 * (it.value.toInt() - 48)).run {
(this % 10) + (this / 10) /* sum both digits */
}
}.sum() % 10}"
}

I understand that obfuscating code like this in a shared code environment would be very bad, but still I think it's great that we can get to do this and that Kotlin avoids so much boilerplate. What do you think about using one-line functions like this one?

I personally like one-line functions as long as they are short but I also prefer breaking things out into smaller functions and/or objects to improve readability, reuse, etc. e.g.:

fun String.plusLuhnCheckDigit() = this + luhnCheckDigit(this)
fun luhnCheckDigit(digits: CharSequence): Char {
return digits.sumByIndexed { index, digit ->
when {
index.isEven -> digit.asInt()
else -> sumDigits(2 * digit.asInt())
}
}.let { sum -> 10 - sum % 10 }.asChar()
}

With the following also defined:

Strings.kt

inline fun CharSequence.sumByIndexed(selector: (Int, Char) -> Int): Int {
return foldIndexed(0) { index, sum, element -> sum + selector(index, element) }
}

Numbers.kt

val Int.isEven: Boolean
get() = and(1) == 0

NumericalChars.kt

fun Char.asInt() = toInt() - 48
fun Int.asChar() = toChar() + 48

IntMath.kt

val Int.magnitude: Int
get() = if (this < 0) -this else this

fun sumDigits(n: Int): Int = if (n.magnitude < 10) n else n % 10 + sumDigits(n / 10)
• Thanks for the comment! As I said, I know there are better ways to implement this, but I wanted to showcase Kotlin's many tools that allow this kind of complex functions to be written in a single line. Also, in your sumDigits function, why do you use an if? You would get the same result always if you just used the code inside the else as n/10 would be 0 when n < 10. – rodolfosrg Aug 26 '16 at 15:28
• @rodolfosrg The sumDigits I've included above is generic and is not limited to 2 digits. It recursively sums the digits. As such, fun sumDigits(n: Int): Int = n % 10 + sumDigits(n / 10) would result in a StackOverflowError. – mfulton26 Aug 26 '16 at 17:22
• Also, I considered fun sumDigits(n: Int): Int = if (n == 0) 0 else n % 10 + sumDigits(n / 10) instead but that would result in additional invocations of sumDigitsand plus (it would always end with an additional + 0 unless the last digit were actually "0"). – mfulton26 Aug 26 '16 at 17:24
• Oh that's right. I didn't notice the recursive part. Thanks! – rodolfosrg Aug 26 '16 at 21:50