Skip to content

Instantly share code, notes, and snippets.

@grahamedgecombe
Created June 11, 2010 19:24
Show Gist options
  • Save grahamedgecombe/434920 to your computer and use it in GitHub Desktop.
Save grahamedgecombe/434920 to your computer and use it in GitHub Desktop.
Unique Candidate Identifier check digit calculator.
// ============================================================================
// Copyright (c) 2010-2011 Graham Edgecombe. All Rights Reserved.
// Unique Candidate Identifier Check Digit Calculator
// ============================================================================
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#define CENTRE_LEN 5
#define BOARD_LEN 1
#define YEAR_LEN 2
#define CANDIDATE_LEN 4
#define CHECK_LEN 1
#define UCI_LEN (CENTRE_LEN + BOARD_LEN + YEAR_LEN + CANDIDATE_LEN + CHECK_LEN)
#define UCI_STR_LEN (UCI_LEN + 4)
#define PRODUCT 16
#define DIVISOR 17
struct uci
{
char centre[CENTRE_LEN + 1];
char board[BOARD_LEN + 1];
char year[YEAR_LEN + 1];
char candidate[CANDIDATE_LEN + 1];
};
char uci_char_to_num(char c, bool letters)
{
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'A' && c <= 'I')
return c - 'A';
else if (letters)
if (c == 'J' || c == 'Q' || c == 'X')
return 10;
else if (c == 'K' || c == 'R' || c == 'Y')
return 11;
else if (c == 'L' || c == 'S' || c == 'Z')
return 12;
else if (c == 'M' || c == 'T')
return 13;
else if (c == 'N' || c == 'U')
return 14;
else if (c == 'O' || c == 'V')
return 15;
else if (c == 'P' || c == 'W')
return 16;
return 0;
};
char uci_check_digit(struct uci *u)
{
unsigned char values[UCI_LEN - CHECK_LEN];
int offset = 0;
for (int i = 0; i < CENTRE_LEN; i++)
values[offset++] = uci_char_to_num(u->centre[i], i < 2);
for (int i = 0; i < BOARD_LEN; i++)
values[offset++] = uci_char_to_num(u->board[i], true);
for (int i = 0; i < YEAR_LEN; i++)
values[offset++] = uci_char_to_num(u->year[i], false);
for (int i = 0; i < CANDIDATE_LEN; i++)
values[offset++] = uci_char_to_num(u->candidate[i], false);
unsigned int sum = 0;
for (int i = 0; i < (UCI_LEN - CHECK_LEN); i++)
sum += (PRODUCT - i) * values[i];
int remainder = sum % DIVISOR;
if (remainder < 8)
return 'A' + remainder;
else if (remainder < 10)
return 'K' + remainder - 8;
else if (remainder == 11)
return 'R';
else if (remainder == 12)
return 'T';
else
return 'V' + remainder - 13;
}
void uci_str(char *str, struct uci *u)
{
char check = uci_check_digit(u);
sprintf(str, "UCI%s%s%s%s%c", u->centre, u->board, u->year, u->candidate, check);
}
int main(int argc, char **argv)
{
struct uci u;
sprintf(u.centre, "68199");
sprintf(u.board, "0");
sprintf(u.year, "01");
sprintf(u.candidate, "2058");
char str[UCI_STR_LEN];
uci_str((char *) &str, &u);
printf("%s\n", str);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment