Credit card numbers are not random; there are a number of embedded codes and there is an overall structural requirement. This script (for the fun of it), validates the structure of a 16-digit number as a potential credit card number. It’s called the Luhn Algorithm. The rest of the code (for the curious) is explained in this Stumbleupon entry.
(*
Take any real credit card number and double every other digit starting on the right.
For each two-digit double, add the digits, otherwise just use the number.
Add these results to all of the original numbers.
If the sum is divisible by 10, the credit card number is properly structured.
This is the Luhn Algorithm that all credit cards use.
*)
validate("4417123456789113") -- uses text to avoid size limit on numbers
to validate(tNum)
set numList to characters of tNum
if (count numList) ≠16 then
display dialog "Must Be 16 Digits!"
return
end if
set tSum to 0
repeat with k from 2 to 16 by 2 -- add every even placed entry
set tSum to tSum + (item k of numList)
end repeat
repeat with j from 15 to 1 by -2 -- double, adjust and add odd placed entries
set double to 2 * (item j of numList)
if double > 9 then set double to 1 + double mod 10 -- just add the digits
set tSum to tSum + double
end repeat
if tSum mod 10 is 0 then
display dialog "Number Structure is Valid."
else
display dialog "Cannot Be a Credit Card Number!"
end if
end validate
ASIDE: Nigel Garvey and other whizzes with modulo arithmetic are invited to make this much more elegant.
Thanks, Adam. That’s very interesting.
You can lose one of the repeats like this:
validate("4417123456789113") -- uses text to avoid size limit on numbers
to validate(tNum)
if (count tNum) ≠16 then
display dialog "Must Be 16 Digits!"
return
end if
set numList to characters of tNum
set tSum to 0
repeat with k from 1 to 15 by 2
tell (item k of numList) * 2 to set tSum to tSum + it div 10 + it mod 10 + (item (k + 1) of numList)
end repeat
if tSum mod 10 is 0 then
display dialog "Number Structure is Valid."
else
display dialog "Cannot Be a Credit Card Number!"
end if
end validate
Or numerically:
validate("4417123456789113")
to validate(tNum)
if (count tNum) ≠16 then
display dialog "Must Be 16 Digits!"
return
end if
set n to tNum as number
set tSum to 0
repeat 8 times
tell n mod 100 div 10 * 2 to set tSum to tSum + it div 10 + it mod 10 + n mod 10
set n to n div 100
end repeat
if tSum mod 10 is 0 then
display dialog "Number Structure is Valid."
else
display dialog "Cannot Be a Credit Card Number!"
end if
end validate
I wish you wouldn’t post things like this just as I’m going to bed.
In fact, since units in addition results aren’t affected by carries, there’s no need to mod by 10 during the calculation. The mod in the test at the end is enough:
validate("4417123456789113")
to validate(tNum)
if (count tNum) ≠16 then
display dialog "Must Be 16 Digits!"
return
end if
set n to tNum as number
set tSum to 0
repeat 8 times
tell n mod 100 div 10 * 2 to set tSum to tSum + it div 10 + it + n
set n to n div 100
end repeat
if tSum mod 10 is 0 then
display dialog "Number Structure is Valid."
else
display dialog "Cannot Be a Credit Card Number!"
end if
end validate
A more interesting variant is:
This contains exactly the same number of the same operators and doesn’t inflate tSum to such a huge size, which may (possibly) reduce the risk of errors.
Very interesting. It’s use could be for assistant scripts or transferred to ASOC or Objective-C for use in buying things.
But, I ask, why do numbers higher than a certain amount (and not in quotes, of course) need to be converted to a different format, and why does AppleScript take the value differently?