Validate and scrub, then foldRight

Luhn
Luhn in Scala
object Luhn {

  def valid(input: String): Boolean = {
    if (input.find(chr => !chr.isDigit && !chr.isSpaceChar) != None)
      return false
    val cleanedInput = input.filter(Character.isDigit)
    if (cleanedInput.length() < 2) return false

    cleanedInput
      .foldRight((1, 0)) { (chr, tup) =>
        val num = chr.asDigit
        tup match {
          case (pos, sum) if pos % 2 == 0 =>
            (pos + 1, sum + (if (num > 4) (num * 2) - 9 else num * 2))
          case (pos, sum) => (pos + 1, sum + num)
        }
      } match {
      case (_, sum) => sum % 10 == 0
    }
  }
}

This approach starts be calling the find() method on the String input to check for any characters that are not a digit or a space. If so, then the input is invalid and the method immediately returns false.

If there are no invalid characters, then the input is filter()ed to remove any spaces. If the length of the input without spaces is less than 2, then it is invalid and the method immediately returns false.

The validated and scrubbed input is passed to the foldRight() method. It is initialized with 1 for the starting position and 0 for the sum, both wrapped in a tuple. The tuple and each character is passed into the lambda where an Int is set from the character and the tuple is then pattern matched to whether the position is even or odd. A new tuple is passed into the next iteration of foldRight(), with the sum increased according to the position, and the position increased by 1. Note that the original tuple does not have its position or sum mutated, but a new tuple is created from the operations on the position and sum, thus supporting immutability.

After foldRight() is done, the final tuple is passed to a match where the sum is checked to be evenly divisible by 10.

9th Oct 2024 · Found it useful?