Skip to content

Instantly share code, notes, and snippets.

@maettig
Forked from 140bytes/LICENSE.txt
Created February 3, 2012 16:02
Show Gist options
  • Save maettig/1730861 to your computer and use it in GitHub Desktop.
Save maettig/1730861 to your computer and use it in GitHub Desktop.
isValidEan13 in 140byt.es

The tiny JavaScript function isValidEan13() (82 bytes currently) returns true if a given [EAN-13](http://en.wikipedia.org/wiki/International_Article_Number_(EAN\)) (International Article Number) or ISBN-13 (International Standard Book Number) is valid. formatEan13() (126 bytes) calculates and appends the checksum (or replaces wrong checksums) and formats the number with spaces.

Both functions accept strings and numbers.

The core of the later function is the call split(/\D*/). The regular expression matches every sequence of non-digits including empty sequences. This splits the input into individual digits and removes all non-digits the same time.

Click here to run the test script.

function(a)
{
for (var b = /\d/g, //initialize regular expression to match single digits
c = 0, //initialize checksum
d,
e = 25; //should be 25 - 13 * 2 = -1 in the end, so `~e` is 0
d = b.exec(a); //fetch a single digit from the input
e -= 2)
c += e % 4 * d; //multiply current digit with 3, 1, 3, 1 and so on
return !(~e | c % 10) //e must be -1 and sum must be 0
}
function(a){for(var b=/\d/g,c=0,d,e=25;d=b.exec(a);e-=2)c+=e%4*d;return!(~e|c%10)}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2012 Thiemo Mättig <http://maettig.com>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "isValidEan13",
"description": "Validate EAN-13 and ISBN-13 Numbers.",
"keywords": [
"checksum",
"ean",
"isbn",
"validation"
]
}
<!DOCTYPE html>
<ul>
<script type="text/javascript">
// 82 bytes
var isValidEan13 = function(a)
{
for (var b = /\d/g, //initialize regular expression to match single digits
c = 0, //initialize checksum
d,
e = 25; //should be 25 - 13 * 2 = -1 in the end, so `~e` is 0
d = b.exec(a); //fetch a single digit from the input
e -= 2)
c += e % 4 * d; //multiply current digit with 3, 1, 3, 1 and so on
return !(~e | c % 10) //e must be -1 and sum must be 0
}
// 126 bytes
var formatEan13 = function(a, b, c)
{
for (a = ('' + a) //force `a` to be a string
.split(/\D*/) //split into digits, remove all non-digits
.slice(0, b = 12), //use the first 12 digits only
c = 9; //this makes the final calculation easier, -1 also works
b--;
a[12] = 9 - c % 10) //append or replace checksum
c += (b * 2 & 2 | 1) * //multiply current digit with 3, 1, 3, 1 and so on
(a[b] += b % 6 ? '' : ' '); //format with spaces
return a.join('') //array to string
}
var tests = ['5 449000 096241', '5 901234 123457', 9783161484100,
'5 449000 096242', 9783161484105, 413456789018, 41345678901800, 413456789018000];
for (var i = 0; i < tests.length; i++)
{
var v = isValidEan13(tests[i]);
var e = formatEan13(tests[i]);
document.write('<li>EAN/ISBN ' +
(v ? '<var>' + tests[i] + '</var>' : '<b>' + tests[i] + '</b>') +
' (a ' + typeof tests[i] + ') is ' +
(v ? '' : 'in') + 'valid. Should be <var>' + e + '</var>.');
}
</script>
</ul>
@tsaniel
Copy link

tsaniel commented Feb 3, 2012

Should the function return false if there are more than 13 digits?

@tsaniel
Copy link

tsaniel commented Feb 3, 2012

Updated: Save 9 bytes.

function(a,b,c,d,e){for(b=/\d/g;c=b.exec(a);e^=2)d=~~d-~e*c;return!(d%10)}

@maettig
Copy link
Author

maettig commented Feb 7, 2012

I must admit, I'm shocked. I expected somebody could save one or two bytes, but golfing 11% away from a 83 bytes function is impressive.

I would like to add the length check, as suggested. Here is what I got so far (84 bytes), based on your version.

function(a){for(var b=/\d/g,c=0,d,e=27;d=b.exec(a);c+=e%4*d)e-=2;return!(--e||c%10)}

@tsaniel
Copy link

tsaniel commented Feb 9, 2012

Save 2 bytes.

function(a){for(var b=/\d/g,c=0,d,e=25;d=b.exec(a);e-=2)c+=e%4*d;return!(~e|c%10)}

@maettig
Copy link
Author

maettig commented Feb 9, 2012

Very good. e goes down to -1 and when inverted with ~e it becomes 0.

@maettig
Copy link
Author

maettig commented Feb 10, 2012

I did an update. Also, I saved a few bytes in the second function.

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