Thursday, February 20, 2014

Olimex Week #43 Programming Challenge



/******Weekend Programming Challenge – Week #43 Bank Card validation *********/



Problem:

Bank card numbers are not random, they carry information for the card processor (Visa/Mastercard etc), bank which issued the card, the account and checksum. More on the subject is available at http://en.wikipedia.org/wiki/Bank_card_number

Make code which enters card number and validate it i.e. writes VALID or INVALID number has been entered.

My solution for Arduino:

//Test number:1234567812345670->ok;1234567812345678-NOK

int test;

void setup()
{
  Serial.begin(9600);
  Serial.println("This program valid or invalid the code of a credit card number, according with the Luhn Method.");
  Serial.println("Please Write your credit card number in the serial monitor and push enter.\n");
}

void loop()
{  
  String CardNumber="";
  if(Serial.available())//Wait until something is writen in the serial port
  { //Reading the message from the serial port  
    delay(100);
    while(Serial.available()>0)  CardNumber.concat((char)Serial.read());
 
    Serial.print("Card Number introduced: "); Serial.println(CardNumber);

    test=luhn(CardNumber);  
   
    Serial.print("The number: ");
    Serial.print(CardNumber);
    if(test==0) Serial.println(" is VALID.");
    else Serial.println(" is INVALID.");
    Serial.println();
  } 
}

/************************************************************************************************************
The Luhn test is used by some credit card companies to distinguish valid credit card numbers from what could be a random selection of digits.
Those companies using credit card numbers that can be validated by the Luhn test have numbers that pass the following test:

   1. Reverse the order of the digits in the number.
   2. Take the first, third, ... and every other odd digit in the reversed digits and sum them to form the partial sum s1
   3. Taking the second, fourth ... and every other even digit in the reversed digits:

      1. Multiply each digit by two and sum the digits if the answer is greater than nine to form partial sums for the even digits
      2. Sum the partial sums of the even digits to form s2

   1. If s1 + s2 ends in zero then the original number is in the form of a valid cre

************************************************************************************************************/
int luhn(String number)
{
 int numberlength=number.length();
 char charBuf[numberlength+1];//I add one more because I've to take account the end of string('\0')
 char copyBuf[numberlength+1];
 int odd=0,even=0,sum=0,checkdigit=0;//Variable that help me in the the process of calculation the validation number
 //String to char array
 number.toCharArray(charBuf,numberlength+1);//This array has the account number in char

 Serial.print("Reverse the order of the digits: ");
 for(int i=0;i<numberlength;i++)
 {
   copyBuf[i]=charBuf[numberlength-1-i];
   Serial.print(copyBuf[i]);
 }

 Serial.println("\n'Double the digits in the odd position of the array and if they are bigger than 9 I must sum the two digits between them.'");
 Serial.print("Array of digits: ");
 for(int i=0;i<numberlength;i++)
 {    
    if(i%2!=0)
    {
       odd=(((int)copyBuf[i])-48)*2;//I sustract 48 for passing char to int according to the ASCII table
       if(odd>9)        odd=1+(odd-10);
       copyBuf[i]=odd;
       Serial.print(odd);
       sum+=odd;
    }
    else
    {
      even=((int)copyBuf[i]-48);//char to int
      copyBuf[i]=even;
      Serial.print(even);
      sum+=even;
    }
 }
 Serial.print("\nSum of all these digits: "); Serial.println(sum);
 Serial.print("Multiply the sum by 9: "); Serial.println(sum*=9);
 checkdigit=sum%10;
 Serial.print("The last digit is the check digit: "); Serial.println(checkdigit);
 Serial.println("The check digit must be 0 for be valid,else will be invalid");

 return checkdigit;
}