Created
July 8, 2011 22:55
-
-
Save mwgamera/1073024 to your computer and use it in GitHub Desktop.
Implementation of Verhoeff scheme adapted to aplhanumeric data
This file contains 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
/* Group operation in D18 (precomputed) */ | |
static int d18_op[36][36] = { | |
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35}, | |
{ 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17, 0,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,18}, | |
{ 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17, 0, 1,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,18,19}, | |
{ 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17, 0, 1, 2,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,18,19,20}, | |
{ 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17, 0, 1, 2, 3,22,23,24,25,26,27,28,29,30,31,32,33,34,35,18,19,20,21}, | |
{ 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17, 0, 1, 2, 3, 4,23,24,25,26,27,28,29,30,31,32,33,34,35,18,19,20,21,22}, | |
{ 6, 7, 8, 9,10,11,12,13,14,15,16,17, 0, 1, 2, 3, 4, 5,24,25,26,27,28,29,30,31,32,33,34,35,18,19,20,21,22,23}, | |
{ 7, 8, 9,10,11,12,13,14,15,16,17, 0, 1, 2, 3, 4, 5, 6,25,26,27,28,29,30,31,32,33,34,35,18,19,20,21,22,23,24}, | |
{ 8, 9,10,11,12,13,14,15,16,17, 0, 1, 2, 3, 4, 5, 6, 7,26,27,28,29,30,31,32,33,34,35,18,19,20,21,22,23,24,25}, | |
{ 9,10,11,12,13,14,15,16,17, 0, 1, 2, 3, 4, 5, 6, 7, 8,27,28,29,30,31,32,33,34,35,18,19,20,21,22,23,24,25,26}, | |
{10,11,12,13,14,15,16,17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,28,29,30,31,32,33,34,35,18,19,20,21,22,23,24,25,26,27}, | |
{11,12,13,14,15,16,17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,29,30,31,32,33,34,35,18,19,20,21,22,23,24,25,26,27,28}, | |
{12,13,14,15,16,17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,30,31,32,33,34,35,18,19,20,21,22,23,24,25,26,27,28,29}, | |
{13,14,15,16,17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,31,32,33,34,35,18,19,20,21,22,23,24,25,26,27,28,29,30}, | |
{14,15,16,17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,32,33,34,35,18,19,20,21,22,23,24,25,26,27,28,29,30,31}, | |
{15,16,17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,33,34,35,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}, | |
{16,17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,34,35,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33}, | |
{17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,35,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34}, | |
{18,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19, 0,17,16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, | |
{19,18,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20, 1, 0,17,16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2}, | |
{20,19,18,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21, 2, 1, 0,17,16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3}, | |
{21,20,19,18,35,34,33,32,31,30,29,28,27,26,25,24,23,22, 3, 2, 1, 0,17,16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4}, | |
{22,21,20,19,18,35,34,33,32,31,30,29,28,27,26,25,24,23, 4, 3, 2, 1, 0,17,16,15,14,13,12,11,10, 9, 8, 7, 6, 5}, | |
{23,22,21,20,19,18,35,34,33,32,31,30,29,28,27,26,25,24, 5, 4, 3, 2, 1, 0,17,16,15,14,13,12,11,10, 9, 8, 7, 6}, | |
{24,23,22,21,20,19,18,35,34,33,32,31,30,29,28,27,26,25, 6, 5, 4, 3, 2, 1, 0,17,16,15,14,13,12,11,10, 9, 8, 7}, | |
{25,24,23,22,21,20,19,18,35,34,33,32,31,30,29,28,27,26, 7, 6, 5, 4, 3, 2, 1, 0,17,16,15,14,13,12,11,10, 9, 8}, | |
{26,25,24,23,22,21,20,19,18,35,34,33,32,31,30,29,28,27, 8, 7, 6, 5, 4, 3, 2, 1, 0,17,16,15,14,13,12,11,10, 9}, | |
{27,26,25,24,23,22,21,20,19,18,35,34,33,32,31,30,29,28, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,17,16,15,14,13,12,11,10}, | |
{28,27,26,25,24,23,22,21,20,19,18,35,34,33,32,31,30,29,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,17,16,15,14,13,12,11}, | |
{29,28,27,26,25,24,23,22,21,20,19,18,35,34,33,32,31,30,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,17,16,15,14,13,12}, | |
{30,29,28,27,26,25,24,23,22,21,20,19,18,35,34,33,32,31,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,17,16,15,14,13}, | |
{31,30,29,28,27,26,25,24,23,22,21,20,19,18,35,34,33,32,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,17,16,15,14}, | |
{32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,35,34,33,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,17,16,15}, | |
{33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,35,34,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,17,16}, | |
{34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,35,16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,17}, | |
{35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} | |
}; | |
/* Inverse element in D18 */ | |
static int d18_inv[36] = { | |
0,17,16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, | |
18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35 | |
}; | |
/* Permutation */ | |
static int P[] = { | |
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 | |
}; | |
/* Apply n-th composition of the permutation */ | |
static int perm(int x, int n) { | |
n %= 600; | |
while (n--) | |
x = P[x]; | |
return x; | |
} | |
/* Translate from alphanumeric ASCII to 0-36 integers */ | |
static int ascii2int(char x) { | |
return (x & 0xF0) == 0x30 ? x - '0' : x - 'A' + 10; | |
} | |
/* Translate from integers to alphanumeric ASCII characters */ | |
static char ascii[] = { | |
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', | |
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', | |
}; | |
static char int2ascii(int x) { | |
return ascii[x]; | |
} | |
/* Compute checksum, correct if zero */ | |
int ver36_check(char *data, int len) { | |
int i = 0, c = 0; | |
while (len--) | |
c = d18_op[c][perm(ascii2int(data[len]),i++)]; | |
return c; | |
} | |
/* Replace last character with correct check digit */ | |
int ver36_insert(char *data, int len) { | |
int i, c = 0; | |
for (i = 1; i < len; i++) | |
c = d18_op[c][perm(ascii2int(data[len-i-1]), i)]; | |
c = d18_inv[c]; | |
data[len-1] = int2ascii(c); | |
return c; | |
} | |
#include <stdio.h> | |
#include <ctype.h> | |
#include <string.h> | |
static int filteralnum(char *str) { | |
int i = 0; | |
char *p = str; | |
while (*p) { | |
if (isalnum(*p)) | |
str[i++] = toupper(*p); | |
p++; | |
} | |
str[i] = '\0'; | |
return i; | |
} | |
int main(int argc, char **argv) { | |
for (--argc, ++argv; argc--; argv++) { | |
int len = filteralnum(*argv); | |
if (ver36_check(*argv, len)) { | |
printf("%s WRONG ", *argv); | |
ver36_insert(*argv, len); | |
printf("CORRECT IS %s\n", *argv); | |
} | |
else | |
printf("%s OK\n", *argv); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment