Skip to content

Instantly share code, notes, and snippets.

@madrobby
Forked from 140bytes/LICENSE.txt
Created May 17, 2011 16:34
Show Gist options
  • Star 40 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save madrobby/976805 to your computer and use it in GitHub Desktop.
Save madrobby/976805 to your computer and use it in GitHub Desktop.
Luhn10 algorithm

Implementation of the Luhn 10 algorithm to check validity of credit card numbers. See http://en.wikipedia.org/wiki/Luhn_algorithm for details on the algorithm.

var validCreditCard = function(a,b,c,d,e){for(d=+a[b=a.length-1],e=0;b--;)c=+a[b],d+=++e%2?2*c%10+(c>4):c;return!(d%10)};

validCreditCard('378282246310005'); //=> true
validCreditCard('378282246310006'); //=> false

// some numbers to test with
// 378282246310005 371449635398431 378734493671000
// 30569309025904 38520000023237 6011111111111117
// 6011000990139424 5555555555554444 5105105105105100
// 4111111111111111 4012888888881881 4222222222222
function(
a, // credit card number (as string)
b, // placeholder
c, // placeholder
d, // placeholder
e // placeholder
){
for(
d = +a[ // value of check digit (unary + coerces into a number)
b = a.length - 1, // index to check digit (last digit in number)
],
e = 0 // index to current digit from right
;
b-- // iterate backwards from second-to-last digit
;
)
c = +a[b], // convert current digit to JavaScript number
d += // increase sum
++e // set current index from right
% 2 ? // if current index from right is even
2 * c % 10 // use the sum of the digits of (2*digit), e.g. 9 => 9*2 => 18 => 1+8 => 9
+ (c > 4) // if c is greater than 4 add 1 (boolean true is coerced into number 1)
: c // if current index is odd, just add the digit
;
return!(
d % 10 // return true if the sum can be diveded by 10 without a remainder
// (the Luhn 10 algorithm is also called the "modulus 10" algorithm)
// learn more at http://en.wikipedia.org/wiki/Luhn_algorithm
)
}
function(a,b,c,d,e){for(d=+a[b=a.length-1],e=0;b--;)c=+a[b],d+=++e%2?2*c%10+(c>4):c;return!(d%10)}
Copyright (c) 2011 Thomas Fuchs, http://mir.aculo.us
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{
"name": "luhn10",
"description": "Credit card number check with the Luhn10 algorithm",
"keywords": [ "creditcard", "luhn10", "validation" ]
}
<div id="log">
</div>
<script>
// unit testing http://140byt.es/#gists/976405
var test = function(a,b,c,d,e,f){c=d=e=0;for(f in a)try{a[f](function(g,h){g?c++:(d++,b(f,'F',h))})}catch(i){e++;b(f,'E',i)}b(c+'A',d+'F',e+'E')};
// luhn10 function
var luhn10 = function(a,b,c,d,e){for(d=+a[b=a.length-1],e=0;b--;)c=+a[b],d+=++e%2?2*c%10+(c>4):c;return!(d%10)};
// output what we're testing here
document.getElementById('log').innerHTML = luhn10.toString()+'<br>';
test({
'testPositives': function(assert){
var numbers = ("378282246310005 371449635398431 378734493671000 30569309025904 38520000023237 6011111111111117 "+
"6011000990139424 5555555555554444 5105105105105100 4111111111111111 4012888888881881 4222222222222").split(" ");
numbers.forEach(function(item){ assert(luhn10(item)) });
},
'testNegatives': function(assert){
var numbers = ("378282246310006 371449635398439 378734493671005 4111111111111112").split(" ");
numbers.forEach(function(item){ assert(!luhn10(item)) });
}
}, function(a,b,c){
// log to debugging element
document.getElementById('log').innerHTML += [a,b,c].join(', ')+'<br>';
});
</script>
@madrobby
Copy link
Author

I'm pretty sure this can be further shortened, if anyone wants to code golf!

@kowsik
Copy link

kowsik commented May 17, 2011

Fits in twitter is all that matters! Very cool!

@OiNutter
Copy link

Gutted! Just did this myself having read this article:

http://www.mint.com/blog/trends/credit-card-code-01202011/

And managed to squeeze it in to a tweet, then read the article comments and found out it was called the Luhn algorithm, which you've already done... better! :)

At least I get to take some tips from your version.

@tsaniel
Copy link

tsaniel commented Nov 12, 2011

My version with some maths which could be faster but 1 byte bigger than yours.

A shorter version but works only under 2147483647.

function(a,b,c,d){for(a*=b=c=10;a/=10;c+=[d=a%10,d*2-(d>4)*9][b++&1])a|=0;return!(c%10)}

@tsaniel
Copy link

tsaniel commented Nov 12, 2011

Now it's down to 84 bytes.

@rconnamacher
Copy link

Not sure if the MIT license is what you want. It's a little over a kilobyte and looks like it requires itself to be included in any JavaScript file containing your function.

What if you just called it public domain, attribution requested to either your name or this github URL?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment