J : Barcode Checker

10Dec12

I recently participated in the Advent Programming Contest organised by the IEEE Student Branch Klagenfurt (with support from Alpen-Adria-Universität Klagenfurt and Universität Passau), achieving a rank of 11th (out of 118 participants); as submissions of solutions to that contest are now closed, I’m posting here the solutions I submitted to that contest.

Problem (J; medium difficulty):

Barcode Checker

In order to speed up handling of parcels, Santa decides to use EAN-13 barcodes as labels. EAN-13 barcode is a 13-digit barcoding standard where the actual information in EAN-13 barcodes is contained in the first 12 digits while the last digit is a checksum digit. The checksum digit must be calculated from the data digits before it can be encoded. The checksum is calculated taking a varying weight value times the value of each of the first 12 digits in the barcode to make a sum. The checksum digit is then the digit which must be added to this sum to get a number evenly divisible by 10 (i.e. the additive inverse of the sum, modulo 10). The weights of the digits alternate between 1 and 3, e.g., it is 1 for the first digit, 3 for the second digit, then 1 again for the third digit and so forth until the 12th digit.

Example calculation

The EAN-13 number 1302459079651 will be checked by calculating the sum as follows:
The digits at odd positions times weight 1: (1+0+4+9+7+6) * 1 = 27
The digits at even positions times weight 3:(3+2+5+0+9+5) * 3 = 72
The sum of both calculates to 99. In order to make the number divisible by 10, the checksum digit must be 1. Actually the checksum digit (last digit) is 1, so the checksum is correct for the EAN-13 number 1302459079651.

Problem

Implement a barcode checker program that reads EAN barcodes in the form n nnnnnn nnnnnn from the standard input. Caclulate the checksum digit and compare it with the checksum digit in the input. If the checksum digit matches, write “Ok!” to the console (without quotes, C programmers don’t forget the newline). If the checksum digit is wrong, write “Wrong checksum, last digit should be d!” with d being the calculated checksum digit. If the given number has less than 13 digits or contains non-numeric characters, write “Error!” to the console. Upon reading an empty line the program shall terminate.

Example

Input

1234567890128
7777777777777
12345
123456789x128
(empty line)

Output

Ok!
Wrong checksum, last digit should be 2!
Error!
Error!

Solution (J.c):

#include <stdio.h>
#include <stdlib.h>

typedef struct t_CharListNode_struct
{
  struct t_CharListNode_struct *m_next;
  char m_char;
}
t_CharListNode;

void p_Delete( t_CharListNode *p );

typedef enum
{
  false = 0,
  true
}
bool;

int main( void )
{
  char c;
  t_CharListNode *first, *last;
  bool cIsNonNumeric;
  size_t l;
  l_LOOP:
    first = NULL;
    cIsNonNumeric = false;
    l = 0;
    do
    {
      scanf( "%c", &c );
      if( c != '\n' )
      {
        t_CharListNode *n = ( t_CharListNode* )malloc( sizeof( t_CharListNode ));
        n->m_next = NULL;
        n->m_char = c;
        if( first == NULL )
          first = n;
        else
          last->m_next = n;
        last = n;
        if(( c < '0' ) || ( c > '9' ))
          cIsNonNumeric = true;
        if( l < ( size_t )-1 )
          l ++;
      }
    }
    while( c != '\n' );
    if( first == NULL )
    {
      p_Delete( first );
      return 0;
    }
    if( cIsNonNumeric || ( l != 13 ))
      printf( "Error" );
    else
    {
      t_CharListNode *n = first;
      int i, oddSum = 0, evenSum = 0, sum;
      bool odd = true;
      while( n->m_next != NULL )
      {
        i = n->m_char - '0';
        if( odd )
          oddSum += i;
        else
          evenSum += i;
        odd = !odd;
        n = n->m_next;
      }
      evenSum *= 3;
      sum = oddSum + evenSum;
      i = 10;
      while( !( i >= sum ))
        i += 10;
      i -= sum;
      if( i == ( last->m_char - '0' ))
        printf( "Ok" );
      else
        printf( "Wrong checksum, last digit should be %d", i );
    }
    printf( "!\n" );
    p_Delete( first );
    goto l_LOOP;
}

void p_Delete( t_CharListNode *p )
{
  if( p != NULL )
  {
    p_Delete( p->m_next );
    free( p );
  }
}

Testing:

gcc -std=c99 -Wall -lm J.c
mv a.out J
./J
1234567890128
Ok!
7777777777777
Wrong checksum, last digit should be 2!
12345
Error!
123456789x128
Error!
Advertisements


No Responses Yet to “J : Barcode Checker”

  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: