Skip to content

Instantly share code, notes, and snippets.

@clneagu
Forked from mwgamera/ver36.js
Last active August 29, 2015 14:27
Show Gist options
  • Save clneagu/0a4ee8cc823ad3f1977e to your computer and use it in GitHub Desktop.
Save clneagu/0a4ee8cc823ad3f1977e to your computer and use it in GitHub Desktop.
Alphanumeric derivative of Verhoeff check digit in javascript.
var Ver36 = function() {
"use strict";
var N = 18, N2 = N*2;
var d18_op; // D18 group operation table
var d18_inv; // D18 group inverse
var perm; // the permutation decomposed into cycles
var a2i,i2a; // ASCII translation tables
var NA=0xff; // invalid digit marker in ASCII table
// initialization code
(function() {
var A8 = typeof Uint8Array != 'undefined' ? Uint8Array : Array;
// prepare Cayley table for D18 group
d18_op = new A8(N2*N2);
var i, j;
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
d18_op[N2*i+j] = (i + j) % N;
for (i = 0; i < N; i++)
for (j = N; j < N2; j++)
d18_op[N2*i+j] = N + (i + j) % N;
for (i = N; i < N2; i++)
for (j = 0; j < N; j++)
d18_op[N2*i+j] = N + (i - j) % N;
for (i = N; i < N2; i++)
for (j = N; j < N2; j++)
d18_op[N2*i+j] = (N + i - j) % N;
// prepare inverse element table
d18_inv = new A8(N2);
d18_inv[0] = 0;
for (i = 1; i < N; i++)
d18_inv[i] = N - i;
for (i = N; i < N2; i++)
d18_inv[i] = i;
// decompose permutation cycles
perm = new Array(N2);
var p = [ // the permutation
29,0,32,11,35,20,7,27,2,4,19,28,30,1,5,12,3,9,16,
22,6,33,8,24,26,21,14,10,34,31,15,25,17,13,23,18
], b = new A8(N2); // assert p.length == N2
i = 0;
while (i < b.length) {
var h = [null], c = h, l = 0;
while (!b[i]) {
var cc = [null, p[i]];
c[0] = cc; c = cc;
b[i] = true;
i = p[i];
l++;
}
c[0] = h[0];
for (var j = 0; j < l; j++) {
var pp = perm[c[1]] = new A8(l);
for (var k = 0; k < l; k++) {
pp[k] = c[1];
c = c[0];
}
c = c[0];
}
for (i = 0; i < b.length && b[i]; i++) {}
}
// set up translation tables
a2i = new A8(256);
for (i = 0; i < a2i.length; i++) a2i[i] = NA;
for (i = 0x30; i < 0x3a; i++) a2i[i] = i - 0x30;
for (i = 0x41; i < 0x5b; i++) a2i[i] = i - 0x41 + 10;
for (i = 0x61; i < 0x7b; i++) a2i[i] = i - 0x61 + 10;
i2a = new A8(N2);
for (i = 0; i < 10; i++) i2a[i] = i + 0x30;
for (i = 10; i < N2; i++) i2a[i] = i + 0x41 - 10;
})();
// group operation
var op = function(i, j) {
return d18_op[N2*i+j];
}
// compute n-th application of the permutation
var nperm = function(i, n) {
return perm[i][n % perm[i].length];
}
// verify correctness of check digit
var verify = function(str) {
var i = 0, c = 0, l = str.length;
while (l--) {
var ch = a2i[str.charCodeAt(l) & 0xff];
if (ch != NA)
c = op(c,nperm(ch,i++));
}
return c;
}
// Create new check digit
var create = function(str) {
var i = 1, c = 0, l = str.length;
while (l--) {
var ch = a2i[str.charCodeAt(l) & 0xff];
if (ch != NA)
c = op(c,nperm(ch,i++));
}
return i2a[d18_inv[c]];
}
// Append check digit to given string
var append = function(str) {
return str + String.fromCharCode(create(str));
}
// export functions
return {
'verify': verify,
'create': create,
'append': append
};
}();
var Ver36=function(){"use strict";function n(c){for(var a=1,b=0,f=c.length;f--;){var d=g[c.charCodeAt(f)&255];d!=255&&(d=l[d][a++%l[d].length],b=h[36*b+d])}return k[i[b]]}var h,i,l,g,k;(function(){var c=typeof Uint8Array!="undefined"?Uint8Array:Array;h=new c(1296);var a,b;for(a=0;a<18;a++)for(b=0;b<18;b++)h[36*a+b]=(a+b)%18;for(a=0;a<18;a++)for(b=18;b<36;b++)h[36*a+b]=18+(a+b)%18;for(a=18;a<36;a++)for(b=0;b<18;b++)h[36*a+b]=18+(a-b)%18;for(a=18;a<36;a++)for(b=18;b<36;b++)h[36*a+b]=(18+a-b)%18;i=
new c(36);i[0]=0;for(a=1;a<18;a++)i[a]=18-a;for(a=18;a<36;a++)i[a]=a;l=Array(36);var f=[29,0,32,11,35,20,7,27,2,4,19,28,30,1,5,12,3,9,16,22,6,33,8,24,26,21,14,10,34,31,15,25,17,13,23,18],d=new c(36);for(a=0;a<d.length;){for(var e=b=[null],m=0;!d[a];){var j=[null,f[a]],e=e[0]=j;d[a]=!0;a=f[a];m++}e[0]=b[0];for(b=0;b<m;b++){a=l[e[1]]=new c(m);for(j=0;j<m;j++)a[j]=e[1],e=e[0];e=e[0]}for(a=0;a<d.length&&d[a];a++);}g=new c(256);for(a=0;a<g.length;a++)g[a]=255;for(a=48;a<58;a++)g[a]=a-48;for(a=65;a<
91;a++)g[a]=a-65+10;for(a=97;a<123;a++)g[a]=a-97+10;k=new c(36);for(a=0;a<10;a++)k[a]=a+48;for(a=10;a<36;a++)k[a]=a+65-10})();return{verify:function(c){for(var a=0,b=0,f=c.length;f--;){var d=g[c.charCodeAt(f)&255];d!=255&&(d=l[d][a++%l[d].length],b=h[36*b+d])}return b},create:n,append:function(c){return c+String.fromCharCode(n(c))}}}();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment