Last active
April 5, 2019 18:35
-
-
Save kirked/3053f6c259bdd576805af8b156feb44c to your computer and use it in GitHub Desktop.
Fast Luhn credit card check in Scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
final object Luhn { | |
/** An O(1) Map[Int, Int] of precomputed double values. */ | |
private[this] final val doubles = Array(0, 2, 4, 6, 8, 1, 3, 5, 7, 9) | |
/** | |
* Validate a card using the Luhn algorithm with a single pass through the string, | |
* no other validation needed prior. | |
* | |
* Pure speed here (only 1 function call to get the byte array). | |
*/ | |
final def check(card: String): Boolean = { | |
val bytes = card.getBytes("UTF-8") | |
val max = bytes.length | |
if (max < 10 || max > 19) false | |
else { | |
var sum = 0 | |
var i = max - 1 | |
var even = true | |
while (i >= 0) { | |
val n = bytes(i) - 0x30 // ASCII/UTF numeric digit range = 0x30 - 0x39 | |
if (n < 0 || n > 9) return false // bail on non-numeric character, also range validation | |
else { | |
sum += (if (even) n else doubles(n)) | |
even = !even | |
i -= 1 | |
} | |
} | |
sum % 10 == 0 | |
} | |
} | |
/** | |
* Validate a card using the Luhn algorithm with a single pass through the string, | |
* no other validation needed prior. | |
* | |
* Idiomatic code. | |
*/ | |
final def checkIdiomatic(card: String): Boolean = { | |
if (card.length < 10 || card.length > 19) false | |
else { | |
val sum = card.reverseIterator.zipWithIndex.foldLeft(0) { | |
case (sum, (ch, i)) => | |
val n = ch - 0x30 // ASCII/UTF numeric digit range = 0x30 - 0x39 | |
if (n < 0 || n > 9) return false // bail on non-numeric character, also range validation | |
else sum + (if (i % 2 == 0) n else doubles(n)) | |
} | |
sum % 10 == 0 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
On my Macbook Pro, JVM and code warmed-up: