Skip to content

Instantly share code, notes, and snippets.

@bhanafee
Last active August 29, 2015 14:07
Show Gist options
  • Save bhanafee/6632948f44de89883759 to your computer and use it in GitHub Desktop.
Save bhanafee/6632948f44de89883759 to your computer and use it in GitHub Desktop.
Compute Luhn checksum for credit card or check digit for ABA Routing Transit Number RTN
trait Checksum {
val seed: Seq[Int]
def op(c: Int, x: Int): Int
def coefficients: Stream[Int] = Stream.continually(seed).flatten
/** Computes the checksum for a sequence of Ints beginning with the least significant. */
def compute(xs: Seq[Int]): Int = (10 - xs.zip(coefficients).map(x => op(x._1, x._2)).sum % 10) % 10
/** Computes the check digit for a string of digits. */
def compute(x: String): Char = compute(Checksum.digits(x)).toString.head
/** Validates that the first Int in a squence is the correct checksum for the remaining valus. */
def validate(xs: Seq[Int]): Boolean = xs.head == compute(xs.tail)
/** Validates that the string of digits has the correct checksum. */
def validate(x: String): Boolean = validate(Checksum.digits(x))
}
object Checksum {
def digits(s: String): Seq[Int] = s.filter('0' to '9' contains _).map(_.asDigit).reverse
}
object RTN extends Checksum {
val seed = Seq(7, 3, 1)
def op(c: Int, x: Int): Int = c * x
}
object Luhn extends Checksum{
val seed = Seq(2, 1)
def op(c: Int, x: Int): Int = {
val p = c * x
if (p < 10) p else p - 9
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment