The Luhn algorithm for verifying credit card numbers, etc

Golfscript - 24 chars

-1%{2+0!:0)*109%+}*10%8=

Explanation:

  1. -1% reverses the string
  2. { begins a block (which we use as a loop). Each character in the strings is pushed as it's ascii value.
    1. 2+ adds 2. (the ascii value of a digit is 48+n, so we have 50+n now and the last digit is n)
    2. 0!:0 inverts the value of 0 and stores it (everything is a variable), so we have 1 on the first iteration, 0 on the second, etc.
    3. )* adds one to this value and multiplies it, so we multiply by 2, then 1, then 2, etc.
    4. 109% is remainder modulo 109. This affects only values 5-9 which have been doubled and reduces them to the correct value.
    5. + adds this value to the running sum
  3. }* ends the block and does a 'fold' operation. First, the first character is pushed (since we have reversed, this is the check digit). Then, alternate pushing and executing the block. Thus, we are using the first character's ascii value as the starting value for the running sum.
  4. 10% takes the remainder modulo 10.
  5. 8= will return 1 if the value is 8. We use this because we did not normalize the first pushed character (the check digit).

One might think that we could use 8- instead of 2+ to save a character by changing 109% to 89%, except then we would need to add a space so the - is subtraction (instead of -0).


GolfScript, 44 chars

-1%{16%}%2/1,\+{(\.{0=2*.9>9*-+}{;}if+}*10%!

Selected commentary

Interestingly, the first two items below demonstrate three completely different uses of the % operator: array selection, map, and mod. Most GolfScript operators are "context-sensitive", giving them hugely divergent behaviours depending on what types the arguments are.

  1. -1% reverses the string. This is important as the digit pairs are counted from the right.
  2. {16%}% converts all the ASCII digits into numbers, by modding them with 16.
  3. 2/ splits the array into groups of 2.
  4. 1, is a cheap way to do [0].
  5. \+ effectively prepends the 0 to the digits array. It does this by swapping then concatenating.

The 0 is prepended in preparation for the fold that comes in next. Rather than taking an explicit initial value, GolfScript's fold uses the first item in the array as the initial value.

Now, let's look at the actual fold function. This function takes two arguments: the folded value, and the current item on the array (which in this case will be an array of 2 or (uncommonly) 1, because of the 2/ earlier). Let's assume the arguments are 1 [2 3].

  1. (\. splits out the leftmost array element, moves the remaining array to the front, then copies it. Stack now looks like: 1 2 [3] [3].
  2. The if checks if the array is empty (which is the case for the last group when dealing with an odd-sized account number). If so, then no special processing happens (just pop off the empty array).
  3. For an even group:
    1. 0= grabs the first (only, in this case) element of the array. 1 2 3
    2. 2* doubles the number. 1 2 6
    3. .9>9*- subtracts 9 from the number if it's greater than 9. Implemented as: copy the number, compare with 9, multiply the result (which is either 0 or 1) with 9, then subtract. 1 2 6
    4. + finally adds that to the first number. 1 8
  4. + (after the if) adds the result of the if to the original value, resulting in the new folded value.

After the folding completes, we simply mod with 10 (10%), and negate the result (!), so that we return 1 iff the sum is a multiple of 10.


Python, 73 69 characters

def P(x):D=map(int,x);return sum(D+[d-d/5*9for d in D[-2::-2]])%10==0