foldRight

Luhn
Luhn in Scala
object Luhn {

  def valid(input: String): Boolean = {
    input
      .foldRight((1, 0)) { (chr, tup) =>
        chr match {
          case chr if chr.isDigit => {
            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)
            }
          }
          case chr if chr.isSpaceChar => tup
          case _                      => (-100, 0)
        }
      } match {
      case (pos, sum) => pos > 2 && sum % 10 == 0
    }
  }
}

This approach starts by calling the foldRight() method on the String input. 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 the character is tested in a match expression. The pattern matching first checks if the character is a digit. If so, an Int is set from the character and the tuple is then 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.

If the character is not a letter, then it is tested for being a space. If it is a space, then the tuple is passed into the next iteration as is, without changing the position or the sum.

It the character is neither a digit nor a space, then the tuple is recreated with a position that is so far negative that it won't pass the final match.

After foldRight() is done, the final tuple is passed to a match where the position is tested to be greater than 2 and the sum is checked to be evenly divisible by 10.

9th Oct 2024 · Found it useful?