Posts Tagged ‘card’

Programming Praxis – Credit Card Validation

April 8, 2011

In today’s Programming Praxis exercise our goal is to write to functions related to the Luhn credit card number verification algorithm: one to check if a number is valid and one to make a valid number from a given number by adding one digit. Let’s get started, shall we?

Some imports:

import Data.Char
import Data.List.HT
import Test.QuickCheck

For both functions we need to calculate the Luhn sum of a number, so let’s start with that. This one simply follows the description given in the exercise text. You could probably speed it up a bit by replacing the multiplication with a lookup table.

luhnSum :: Integral a => a -> a
luhnSum n = digitSum a + digitSum (show . (* 2) . digitToInt =<< b)
    where [a,b] = sliceHorizontal 2 . reverse $ show n
          digitSum = sum . map (fromIntegral . digitToInt)

Checking if a number is valid is trivial: just see if the Luhn sum is zero.

isValid :: Integral a => a -> Bool
isValid n = mod (luhnSum n) 10 == 0

Making a valid number means adding the complement of the Luhn sum of 10 times the number (to account for the digit that will be added on the end) to the end of the number. The outer modulo is to account for the case where the Luhn sum is zero.

makeValid :: Integral a => a -> a
makeValid n = 10*n + mod (10 - mod (luhnSum $ 10*n) 10) 10

Some testing to see if everthing is working properly:

prop_luhn :: Integer -> Property
prop_luhn n = n >= 0 ==> isValid (makeValid n)

main :: IO ()
main = do print $ isValid 0
          print $ isValid 34
          print $ isValid 117
          print $ isValid 49927398716
          print . not $ isValid 49927398715
          print $ makeValid 4992739871 == 49927398716
          quickCheck prop_luhn

Yup. Have fun committing credit card fraud 🙂