Luhn test of credit card numbers
You are encouraged to solve this task according to the task description, using any language you may know.
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:
- Reverse the order of the digits in the number.
- Take the first, third, ... and every other odd digit in the reversed digits and sum them to form the partial sum s1
- Taking the second, fourth ... and every other even digit in the reversed digits:
- Multiply each digit by two and sum the digits if the answer is greater than nine to form partial sums for the even digits
- Sum the partial sums of the even digits to form s2
- If s1 + s2 ends in zero then the original number is in the form of a valid credit card number as verified by the Luhn test.
For example, if the trial number is 49927398716:
Reverse the digits:
61789372994
Sum the odd digits:
6 + 7 + 9 + 7 + 9 + 4 = 42 = s1
The even digits:
1, 8, 3, 2, 9
Two times each even digit:
2, 16, 6, 4, 18
Sum the digits of each multiplication:
2, 7, 6, 4, 9
Sum the last:
2 + 7 + 6 + 4 + 9 = 28 = s2
s1 + s2 = 70 which ends in zero which means that 49927398716 passes the Luhn test
The task is to write a function/method/procedure/subroutine that will validate a number with the Luhn test, and use it to validate the following numbers:
- 49927398716
- 49927398717
- 1234567812345678
- 1234567812345670
Cf. SEDOL
[edit] ABAP
METHOD luhn_check.
DATA: sum(1) TYPE n VALUE 0. " Sum of checksum.
DATA: current TYPE i. " Current digit.
DATA: odd TYPE i VALUE 1. " Multiplier.
DATA: len TYPE i. " String crowler.
" Luhn algorithm.
len = NUMOFCHAR( pi_string ) - 1.
WHILE ( len >= 0 ).
current = pi_string+len(1) * odd.
IF ( current > 9 ).
current = current - 9. " Digits sum.
ENDIF.
sum = sum + current.
odd = 3 - odd. " 1 <--> 2 Swich
len = len - 1. " Move to next charcter.
ENDWHILE.
" Validation check.
IF ( sum = 0 ).
pr_valid = abap_true.
ELSE.
pr_valid = abap_false.
ENDIF.
ENDMETHOD.
[edit] ACL2
(include-book "arithmetic-3/top" :dir :system)
(defun digits (n)
(if (zp n)
nil
(cons (mod n 10)
(digits (floor n 10)))))
(defun sum (xs)
(if (endp xs)
0
(+ (first xs)
(sum (rest xs)))))
(defun double-and-sum-digits (xs)
(if (endp xs)
nil
(cons (sum (digits (* 2 (first xs))))
(double-and-sum-digits (rest xs)))))
(defun dmx (xs)
(if (endp (rest xs))
(mv xs nil)
(mv-let (odds evens)
(dmx (rest (rest xs)))
(mv (cons (first xs) odds)
(cons (second xs) evens)))))
(defun luhn (n)
(mv-let (odds evens)
(dmx (digits n))
(= (mod (+ (sum odds)
(sum (double-and-sum-digits evens)))
10)
0)))
Output:
> (luhn 49927398716) T > (luhn 49927398717) NIL > (luhn 1234567812345678) NIL > (luhn 1234567812345670) T
[edit] ActionScript
function isValid(numString:String):Boolean
{
var isOdd:Boolean = true;
var oddSum:uint = 0;
var evenSum:uint = 0;
for(var i:int = numString.length - 1; i >= 0; i--)
{
var digit:uint = uint(numString.charAt(i))
if(isOdd) oddSum += digit;
else evenSum += digit/5 + (2*digit) % 10;
isOdd = !isOdd;
}
if((oddSum + evenSum) % 10 == 0) return true;
return false;
}
trace(isValid("49927398716"));
trace(isValid("49927398717"));
trace(isValid("1234567812345678"));
trace(isValid("1234567812345670"));
[edit] Ada
with Ada.Text_IO; use Ada.Text_IO;
procedure luhn is
function luhn_test(num : String) return Boolean is
sum : Integer := 0;
odd : Boolean := True;
int : Integer;
begin
for p in reverse num'Range loop
int := Integer'Value(num(p..p));
if odd then
sum := sum + int;
else
sum := sum + (int*2 mod 10) + (int / 5);
end if;
odd := not odd;
end loop;
return (sum mod 10)=0;
end luhn_test;
begin
put_line(Boolean'Image(luhn_test("49927398716")));
put_line(Boolean'Image(luhn_test("49927398717")));
put_line(Boolean'Image(luhn_test("1234567812345678")));
put_line(Boolean'Image(luhn_test("1234567812345670")));
end luhn;
Sample output:
TRUE FALSE FALSE TRUE
[edit] ALGOL 68
- note: This specimen retains the original C coding style.PROC to int = (CHAR c)INT:
ABS c - ABS "0";
PROC confirm = (STRING id)BOOL:
(
BOOL is odd digit := TRUE;
INT s := 0;
STRING cp;
FOR cp key FROM UPB id BY -1 TO LWB id DO
INT k := to int(id[cp key]);
s +:=
IF is odd digit THEN k
ELIF k /= 9 THEN 2*k MOD 9
ELSE 9
FI;
is odd digit := NOT is odd digit
OD;
0 = s MOD 10
);
main:
(
[]STRING t cases = (
"49927398716",
"49927398717",
"1234567812345678",
"1234567812345670"
);
FOR cp key TO UPB t cases DO
STRING cp = t cases[cp key];
print((cp, ": ", confirm(cp), new line))
OD
)
Output:
49927398716: T 49927398717: F 1234567812345678: F 1234567812345670: T
[edit] APL
r←LuhnTest digits;even;odd;SumEven
(odd even)←↓⍉⍎¨{(n,2)⍴(⍵,'0')↑⍨2×n←⌈(⍴⍵)÷2}⌽digits
SumEven←{+/+/¨⍎¨¨⍕¨2×⍵}
r←'0'=⊃¯1↑⍕(+/odd)+(SumEven even)
Sample Output:
1 0 0 1
∇ ret←LuhnTest num;s1;s2
[1] num←⌽((⌈10⍟num)/10)⊤num
[2] s1←+/((⍴num)⍴1 0)/num
[3] s2←+/∊(⊂10 10)⊤¨2×((⍴num)⍴0 1)/num
[4] ret←0=10⊤s1+s2
∇
Sample Output:
LuhnTest¨ 49927398716 49927398717 1234567812345678 1234567812345670 1 0 0 1
[edit] AutoHotkey
; Originally submitted by Laszlo:
; http://www.autohotkey.com/forum/post-229412.html#229412
MsgBox % LuhnTest(49927398716)
MsgBox % LuhnTest(49927398717)
MsgBox % LuhnTest(1234567812345678)
MsgBox % LuhnTest(1234567812345670)
Return
;-----------------------------
LuhnTest(Number)
{
MultFactor := 2 - ( StrLen(Number) & 1 ) , Sum := 0
Loop, Parse, Number
Sum += ( ( 9 < ( Temp := MultFactor * A_LoopField ) ) ? Temp - 9 : Temp ) , MultFactor := 3 - MultFactor
Return !Mod(Sum,10)
}
[edit] AutoIt
Output :
Global $avarray[4] = [49927398716, 49927398717, 1234567812345678, 1234567812345670]
For $i = 0 To 3
checkLuhn($avarray[$i])
Next
Func checkLuhn($number)
$sum = 0
$numDigits = StringSplit($number, "")
For $i = $numDigits[0] - 1 To 1 Step -2
$numDigits[$i] = $numDigits[$i] * 2
If $numDigits[$i] >= 10 Then $numDigits[$i] -= 9
Next
For $i = 1 To $numDigits[0]
$sum += $numDigits[$i]
Next
If StringRight($sum, 1) = "0" Then
ConsoleWrite("Luhn-Check (" & $number & ") : True" & @CRLF)
Return True
Else
ConsoleWrite("Luhn-Check (" & $number & ") : False" & @CRLF)
Return False
EndIf
EndFunc ;==>checkLuhn
Luhn-Check (49927398716) : True Luhn-Check (49927398717) : False Luhn-Check (1234567812345678) : False Luhn-Check (1234567812345670) : True
[edit] AWK
#!/usr/bin/awk -f
BEGIN {
A[1] = 49927398716;
A[2] = 49927398717;
A[3] = 1234567812345678;
A[4] = 1234567812345670;
for (k in A) print "isLuhn("A[k]"): ",isLuhn(A[k]);
}
function isLuhn(cardno) {
m = "246813579";
n = length(cardno);
for (k = n; 0 < k; k -= 2) {
s += substr(cardno, k, 1);
}
for (k = n-1; 0 < k; k -= 2) {
s += substr(m, substr(cardno, k, 1), 1);
}
return ((s%10)==0);
}
Output:
isLuhn(1234567812345670): 1 isLuhn(49927398716): 1 isLuhn(49927398717): 0 isLuhn(1234567812345678): 0
[edit] Bash
#!/bin/bash
function luhn_validate # <numeric-string>
{
num=$1
shift 1
len=${#num}
is_odd=1
sum=0
for((t = len - 1; t >= 0; --t)) {
digit=${num:$t:1}
if [[ $is_odd -eq 1 ]]; then
sum=$(( sum + $digit ))
else
sum=$(( $sum + ( $digit != 9 ? ( ( 2 * $digit ) % 9 ) : 9 ) ))
fi
is_odd=$(( ! $is_odd ))
}
# NOTE: returning exit status of 0 on success
return $(( 0 != ( $sum % 10 ) ))
}
function print_result # <numeric-string>
{
if luhn_validate "$1"; then
echo "$1 is valid"
else
echo "$1 is not valid"
fi
}
print_result "49927398716"
print_result "49927398717"
print_result "1234567812345678"
print_result "1234567812345670"
Output:
49927398716 is valid 49927398717 is not valid 1234567812345678 is not valid 1234567812345670 is valid
[edit] BBC BASIC
FOR card% = 1 TO 4
READ cardnumber$
IF FNluhn(cardnumber$) THEN
PRINT "Card number " cardnumber$ " is valid"
ELSE
PRINT "Card number " cardnumber$ " is invalid"
ENDIF
NEXT card%
END
DATA 49927398716, 49927398717, 1234567812345678, 1234567812345670
DEF FNluhn(card$)
LOCAL I%, L%, N%, S%
L% = LEN(card$)
FOR I% = 1 TO L%
N% = VAL(MID$(card$, L%-I%+1, 1))
IF I% AND 1 THEN
S% += N%
ELSE
N% *= 2
S% += N% MOD 10 + N% DIV 10
ENDIF
NEXT
= (S% MOD 10) = 0
[edit] Bracmat
( luhn
= sum odd even
. 0:?sum
& rev$!arg:?arg
& whl
' ( @( !arg
: %?odd
( %?even ?arg
| :?arg&0:?even
)
)
& !odd+mod$(2*!even.10)+div$(!even.5)+!sum:?sum
)
& mod$(!sum.10):0
)
& ( test
=
. out
$ (!arg ":" (luhn$!arg&true|false))
)
& test$49927398716
& test$49927398717
& test$1234567812345678
& test$1234567812345670
& ;
Output:
49927398716 : true 49927398717 : false 1234567812345678 : false 1234567812345670 : true
[edit] C
#include <string.h>
#include <stdio.h>
int luhn(const char* cc)
{
const int m[] = {0,2,4,6,8,1,3,5,7,9}; // mapping for rule 3
int i, odd = 1, sum = 0;
for (i = strlen(cc); i--; odd = !odd) {
int digit = cc[i] - '0';
sum += odd ? digit : m[digit];
}
return sum % 10 == 0;
}
int main()
{
const char* cc[] = {
"49927398716",
"49927398717",
"1234567812345678",
"1234567812345670",
0
};
int i;
for (i = 0; cc[i]; i++)
printf("%16s\t%s\n", cc[i], luhn(cc[i]) ? "ok" : "not ok");
return 0;
}
- Output:
49927398716 ok
49927398717 not ok
1234567812345678 not ok
1234567812345670 ok
[edit] C++
#include <iostream>
using namespace std;
int toInt(const char c)
{
return c-'0';
}
int confirm( const char *id)
{
bool is_odd_dgt = true;
int s = 0;
const char *cp;
for(cp=id; *cp; cp++);
while(cp > id) {
--cp;
int k = toInt(*cp);
if (is_odd_dgt) {
s += k;
}
else {
s += (k!=9)? (2*k)%9 : 9;
}
is_odd_dgt = !is_odd_dgt;
}
return 0 == s%10;
}
int main( )
{
const char * t_cases[] = {
"49927398716",
"49927398717",
"1234567812345678",
"1234567812345670",
NULL,
};
for ( const char **cp = t_cases; *cp; cp++) {
cout << *cp << ": " << confirm(*cp) << endl;
}
return 0;
}
[edit] C#
using System;
using System.Linq;
namespace Luhn
{
class Program
{
public static bool luhn(long n)
{
long nextdigit, sum = 0;
bool alt = false;
while (n != 0)
{
nextdigit = n % 10;
if (alt)
{
nextdigit *= 2;
nextdigit -= (nextdigit > 9) ? 9 : 0;
}
sum += nextdigit;
alt = !alt;
n /= 10;
}
return (sum % 10 == 0);
}
public static bool luhnLinq(long n)
{
string s = n.ToString();
return s.Select((c, i) => (c - '0') << ((s.Length - i - 1) & 1)).Sum(n => n > 9 ? n - 9 : n) % 10 == 0;
}
static void Main(string[] args)
{
long[] given = new long[] {49927398716, 49927398717, 1234567812345678, 1234567812345670};
foreach (long num in given)
{
string valid = (luhn(num)) ? " is valid" : " is not valid";
Console.WriteLine(num + valid);
}
}
}
}
49927398716 is valid 49927398717 is not valid 1234567812345678 is not valid 1234567812345670 is valid
[edit] Caché ObjectScript
Class Utils.Validate [ Abstract ]
{
ClassMethod DoLuhnCheck(num As %String) As %Boolean
{
Set sum=0, num=$Reverse(num)
For pos=1:1:$Length(num) {
Set dig=$Extract(num, pos)
Set sum=sum+$Select(pos#2: dig, 1: (dig*2#10)+(dig\5))
}
Quit sum#10=0
}
}
- Examples:
USER>For { Read ccn Quit:ccn="" Write ": "_##class(Utils.Validate).DoLuhnCheck(ccn), ! }
49927398716: 1
49927398717: 0
1234567812345678: 0
1234567812345670: 1
USER>
[edit] Clojure
(defn- digits [n]
(map #(Character/digit % 10) (str n)))
(defn luhn? [n]
(let [sum (reduce + (map
(fn [d idx]
(if (even? idx)
(reduce + (digits (* d 2)))
d))
(reverse (digits n))
(iterate inc 1)))]
(zero? (mod sum 10))))
(doseq [n [49927398716 49927398717 1234567812345678 1234567812345670]]
(println (luhn? n)))
[edit] Common Lisp
(defun luhn (n)
(labels ((sum-digits (n) (if (> n 9) (- n 9) n)))
(let ((n* (reverse n)) (l (length n)))
(let ((s1 (loop for i from 0 below l by 2
summing (digit-char-p (aref n* i))))
(s2 (loop for i from 1 below l by 2
summing (sum-digits (* 2 (digit-char-p (aref n* i)))))))
(zerop (mod (+ s1 s2) 10))))))
Another version, using Maciej Pasternacki's reader macros for function composition and currying in the curly package:
(require :curly)
(use-package :curly)
(enable-curly-syntax)
(defun luhn (seq)
(labels ((sum-digits (n) (if (> n 9) (- n 9) n)))
(funcall {zerop (mod * 10) (apply #'+) (mapcar #'sum-digits)
(mapcar #'* '#1=(1 2 . #1#)) (map 'list #'digit-char-p) reverse} seq)))
[edit] COBOL
works for opencobol and ibm enterprise cobol for z/os
IDENTIFICATION DIVISION.
PROGRAM-ID. LUHNTEST.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
data division.
WORKING-STORAGE SECTION.
01 inp-card.
03 inp-card-ch pic x(01) occurs 20 times.
01 ws-result pic 9(01).
88 pass-luhn-test value 0.
PROCEDURE DIVISION.
move "49927398716" to inp-card
perform test-card
move "49927398717" to inp-card
perform test-card
move "1234567812345678" to inp-card
perform test-card
move "1234567812345670" to inp-card
perform test-card
stop run
.
test-card.
call "LUHN" using inp-card, ws-result
if pass-luhn-test
display "input=" inp-card "pass"
else
display "input=" inp-card "fail"
.
END PROGRAM LUHNTEST.
IDENTIFICATION DIVISION.
PROGRAM-ID. LUHN.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 maxlen pic 9(02) comp value 16.
01 inplen pic 9(02) comp value 0.
01 i pic 9(02) comp value 0.
01 j pic 9(02) comp value 0.
01 l pic 9(02) comp value 0.
01 dw pic 9(02) comp value 0.
01 ws-total pic 9(03) comp value 0.
01 ws-prod pic 99.
01 filler redefines ws-prod.
03 ws-prod-tens pic 9.
03 ws-prod-units pic 9.
01 ws-card.
03 filler occurs 16 times depending on maxlen.
05 ws-card-ch pic x(01).
05 ws-card-digit redefines ws-card-ch pic 9(01).
LINKAGE SECTION.
01 inp-card.
03 inp-card-ch pic x(01) occurs 20 times.
01 ws-result pic 9(01).
88 pass-luhn-test value 0.
PROCEDURE DIVISION using inp-card, ws-result.
perform varying i from 1 by +1
until i > maxlen
or inp-card-ch (i) = space
end-perform
compute l = i - 1
compute inplen = l
perform varying j from 1 by +1
until j > inplen
if l < 1
move "0" to ws-card-ch (j)
else
move inp-card-ch (l) to ws-card-ch (j)
compute l = l - 1
end-if
end-perform
move 0 to ws-total
perform varying i from 1 by +1
until i > inplen
compute dw = 2 - (i - 2 * function integer (i / 2))
compute ws-prod = ws-card-digit (i) * dw
compute ws-total = ws-total
+ ws-prod-tens
+ ws-prod-units
end-perform
compute ws-result = ws-total - 10 * function integer (ws-total / 10)
goback
.
END PROGRAM LUHN.
Sample output:
input=49927398716 pass input=49927398717 fail input=1234567812345678 fail input=1234567812345670 pass
[edit] D
[edit] Shorter Version
import std.algorithm;
bool luhnTest(in string num) @safe pure nothrow {
uint sum;
foreach_reverse (immutable i, immutable n; num) {
immutable uint ord = n - '\u0030';
sum += ((num.length - i) & 1) ? ord : ord / 5 + (2 * ord) % 10;
}
return sum % 10 == 0;
}
void main() {
immutable data = ["49927398716",
"49927398717",
"1234567812345678",
"1234567812345670"];
assert(data.map!luhnTest.equal([true, false, false, true]));
}
[edit] Stronger Statically Typed Version
import std.stdio;
struct Interval(T) {
immutable T a, b;
this(in T a_, in T b_) pure nothrow {
this.a = a_;
this.b = b_;
}
bool opBinaryRight(string op="in")(in T x) const pure nothrow {
return x >= a && x <= b;
}
pure nothrow const invariant() {
assert(a <= b);
}
}
Interval!T interval(T)(in T a, in T b) pure nothrow {
return Interval!T(a, b);
}
bool luhnTest(in string num) pure nothrow
in {
assert(num.length <= 20);
} body {
int sum = 0;
bool od = true;
bool ok = true;
immutable int numLen = num.length;
foreach_reverse (immutable p; 0 .. numLen) {
immutable int i = num[p] - '0';
if (i !in interval(0, 9)) {
ok = false;
break;
}
immutable int x = ((i * 2) % 10) + (i / 5);
assert((numLen - p) in interval(0, 19));
assert(sum in interval(0, (numLen - p) * 10));
assert(i in interval(0, 9));
assert(x in interval(0, 9));
sum += od ? i : x;
od = !od;
}
return ok && (sum % 10) == 0;
}
void main() {
foreach (immutable n; ["49927398716", "49927398717",
"1234567812345678", "1234567812345670",
"123456781234567D"])
writefln("%s is %svalid", n, luhnTest(n) ? "" : "not ");
}
[edit] Euphoria
function luhn(sequence cc)
integer isOdd, oddSum, evenSum, digit
isOdd = 1
oddSum = 0
evenSum = 0
for i = length(cc) to 1 by -1 do
digit = cc[i] - '0'
if isOdd then
oddSum += digit
else
evenSum += floor(digit / 5) + remainder(2 * digit, 10)
end if
isOdd = not isOdd
end for
return not remainder(oddSum + evenSum, 10)
end function
constant cc_numbers = {
"49927398716",
"49927398717",
"1234567812345678",
"1234567812345670"
}
for i = 1 to length(cc_numbers) do
printf(1,"%s = %d\n", {cc_numbers[i], luhn(cc_numbers[i])})
end for
Output:
49927398716 = 1 49927398717 = 0 1234567812345678 = 0 1234567812345670 = 1
[edit] F#
let luhn (s:string) =
let rec g r c = function
| 0 -> r
| i ->
let d = ((int s.[i - 1]) - 48) <<< c
g (r + if d < 10 then d else d - 9) (1 - c) (i - 1)
(g 0 0 s.Length) % 10 = 0
[edit] Factor
USING: kernel math math.parser math.order math.ranges sequences ;
IN: luhn
: reversed-digits ( n -- list )
{ } swap
[ dup 0 > ]
[ 10 /mod swapd suffix swap ]
while drop ;
: luhn-digit ( n -- n )
reversed-digits dup length iota [
2dup swap nth
swap odd? [ 2 * 10 /mod + ] when
] map sum 10 mod
nip ;
: luhn? ( n -- ? )
luhn-digit 0 = ;
Output:
( scratchpad ) 49927398716 luhn? . t ( scratchpad ) 49927398717 luhn? . f ( scratchpad ) 1234567812345678 luhn? . f ( scratchpad ) 1234567812345670 luhn? . t
[edit] Forth
: luhn ( addr len -- ? )
0 >r over + ( R: sum )
begin 1- 2dup <=
while \ odd
dup c@ [char] 0 -
r> + >r
1- 2dup <=
while \ even
dup c@ [char] 0 -
2* 10 /mod + \ even digits doubled, split, and summed
r> + >r
repeat then
2drop r> 10 mod 0= ;
s" 49927398716" luhn . \ -1
s" 49927398717" luhn . \ 0
s" 1234567812345678" luhn . \ 0
s" 1234567812345670" luhn . \ -1
[edit] Fortran
program luhn
implicit none
integer :: nargs
character(len=20) :: arg
integer :: alen, i, dr
integer, allocatable :: number(:)
integer, parameter :: drmap(0:9) = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
! Get number
nargs = command_argument_count()
if (nargs /= 1) then
stop
end if
call get_command_argument(1, arg, alen)
allocate(number(alen))
do i=1, alen
number(alen-i+1) = iachar(arg(i:i)) - iachar('0')
end do
! Calculate number
dr = 0
do i=1, alen
dr = dr + merge(drmap(number(i)), number(i), mod(i,2) == 0)
end do
if (mod(dr,10) == 0) then
write(*,'(a,i0)') arg(1:alen)//' is valid'
else
write(*,'(a,i0)') arg(1:alen)//' is not valid'
end if
end program luhn
! Results:
! 49927398716 is valid
! 49927398717 is not valid
! 1234567812345678 is not valid
! 1234567812345670 is valid
[edit] GAP
IsLuhn := function(n)
local c, d, i, j, r;
d := "0123456789";
j := 1;
r := 0;
for c in Reversed(String(n)) do
i := Position(d, c);
if i = fail then
continue;
fi;
i := j*(i - 1);
r := r + QuoInt(i, 10) + RemInt(i, 10);
j := 3 - j;
od;
return RemInt(r, 10) = 0;
end;
List([49927398716, 49927398717, 1234567812345678, 1234567812345670], IsLuhn);
# [ true, false, false, true ]
# Will also work on strings, and will skip non-digits
IsLuhn("4-992-739-871-6");
# true
[edit] Go
package main
import (
"fmt"
"strings"
)
const input = `49927398716
49927398717
1234567812345678
1234567812345670`
var t = [...]int{0, 2, 4, 6, 8, 1, 3, 5, 7, 9}
func luhn(s string) bool {
odd := len(s) & 1
var sum int
for i, c := range s {
if c < '0' || c > '9' {
return false
}
if i&1 == odd {
sum += t[c-'0']
} else {
sum += int(c - '0')
}
}
return sum%10 == 0
}
func main() {
for _, s := range strings.Split(input, "\n") {
fmt.Println(s, luhn(s))
}
}
Output:
49927398716 true 49927398717 false 1234567812345678 false 1234567812345670 true
[edit] Groovy
def checkLuhn(number) {
int total
(number as String).reverse().eachWithIndex { ch, index ->
def digit = Integer.parseInt(ch)
total += (index % 2 ==0) ? digit : [0, 2, 4, 6, 8, 1, 3, 5, 7, 9][digit]
}
total % 10 == 0
}
Testing the function:
def verifyLuhn(number, expected) {
println "Checking: $number (${checkLuhn(number)})"
assert expected == checkLuhn(number)
}
[49927398716: true, 49927398717: false, 1234567812345678: false, 1234567812345670: true].each { number, expected ->
verifyLuhn number, expected
}
Output:
Checking: 49927398716 (true) Checking: 49927398717 (false) Checking: 1234567812345678 (false) Checking: 1234567812345670 (true)
[edit] Haskell
import Data.Char (digitToInt)
luhn = (0 ==) . (`mod` 10) . sum . map (uncurry (+) . (`divMod` 10)) .
zipWith (*) (cycle [1,2]) . map digitToInt . reverse
Sample output
map luhn ["49927398716", "49927398717", "1234567812345678", "1234567812345670"]
[True,False,False,True]
[edit] HicEst
CHARACTER numbers="49927398716 49927398717 1234567812345678 1234567812345670 "
DO nr = 1, 4
EDIT(Text=numbers, ITeM=nr, Parse=number)
sum_odds = 0
sum_even = 0
DO i = LEN(number), 1, -2
sum_odds = sum_odds + ICHAR(number(i)) - 48
IF(i > 1) THEN
even2 = 2 * (ICHAR(number(i-1)) - 48)
sum_even = sum_even + MOD(even2, 10) + INT(even2/10)
ENDIF
ENDDO
valid = (0 == MOD(sum_odds + sum_even, 10))
WRITE() number, " is ", "invalid"(1 + 2*valid:)
ENDDO
49927398716 is valid 49927398717 is invalid 1234567812345678 is invalid 1234567812345670 is valid
[edit] Icon and Unicon
We use map to pre-compute the sum of doubled digits.
procedure main(aL)
every write(i := !aL ," - ", ((\isluhn10(i),"valid")|"invalid") \ 1)
end
procedure isluhn10(i) #: isluhn10(i) returns i (if i passes luhn10) or fails
local sum
sum :=0
reverse(integer(i)) ? while not pos(0) do {
sum +:= move(1)
sum +:= map(move(1),"0123456789","0246813579")
}
return (sum % 10 = 0,i)
end
Sample output
# luhn10 49927398716 49927398717 1234567812345678 1234567812345670 49927398716 - valid 49927398717 - invalid 1234567812345678 - invalid 1234567812345670 - valid
[edit] J
We can treat the odd digits the same as even digits, except that they are not doubled. Also, we do not need the intermediate sums.
luhn=: 0 = 10 (| +/@,) 10 #.inv 1 2 *&|: _2 "."0\ |.
Example use:
luhn&> '49927398716';'49927398717';'1234567812345678';'1234567812345670'
1 0 0 1
Interpreting that example: In J, 1 is true, 0 is false, so the first and last provided digit sequences were valid and the middle two were not.
[edit] Java
public class Luhn {
public static void main(String[] args) {
System.out.println(luhnTest("49927398716"));
System.out.println(luhnTest("49927398717"));
System.out.println(luhnTest("1234567812345678"));
System.out.println(luhnTest("1234567812345670"));
}
public static boolean luhnTest(String number){
int s1 = 0, s2 = 0;
String reverse = new StringBuffer(number).reverse().toString();
for(int i = 0 ;i < reverse.length();i++){
int digit = Character.digit(reverse.charAt(i), 10);
if(i % 2 == 0){//this is for odd digits, they are 1-indexed in the algorithm
s1 += digit;
}else{//add 2 * digit for 0-4, add 2 * digit - 9 for 5-9
s2 += 2 * digit;
if(digit >= 5){
s2 -= 9;
}
}
}
return (s1 + s2) % 10 == 0;
}
}
Output:
true false false true
[edit] JavaScript
Using prototype.
mod10check = function(cc) {
return $A(cc).reverse().map(Number).inject(0, function(s, d, i) {
return s + (i % 2 == 1 ? (d == 9 ? 9 : (d * 2) % 9) : d);
}) % 10 == 0;
};
['49927398716','49927398717','1234567812345678','1234567812345670'].each(function(i){alert(mod10check(i))});
Without any library.
var LuhnCheck = (function()
{
var luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
return function(str)
{
var counter = 0;
var incNum;
var odd = false;
var temp = String(str).replace(/[^\d]/g, "");
if ( temp.length == 0)
return false;
for (var i = temp.length-1; i >= 0; --i)
{
incNum = parseInt(temp.charAt(i), 10);
counter += (odd = !odd)? incNum : luhnArr[incNum];
}
return (counter%10 == 0);
}
})();
Highly compressed version.
var luhn10 = function(a,b,c,d,e) {
for(d = +a[b = a.length-1], e=0; b--;)
c = +a[b], d += ++e % 2 ? 2 * c % 10 + (c > 4) : c;
return !(d%10)
};
// returns true
luhn10('4111111111111111')
// returns false
luhn10('4111111111111112')
[edit] K
so: {+/x@2*!_ceil(#x)%2}
se: {+/{+/0$'$x}'2*x@1+2*!(#x)%2}
luhn: {n:|0$'$x; 0=((se n)+so n)!10}
luhn2: {~(+/,//10_vs'1 2*+-1 2#((#n)!2){x,0}/n:0$'|$x)
Example:
luhn'49927398716 49927398717 1234567812345678 1234567812345670
1 0 0 1
luhn2'49927398716 49927398717 1234567812345678 1234567812345670
1 0 0 1
[edit] K3
luhn:{[cc]
digits:0$/:|cc / convert chars to digit ints
s:digits*(#cc)#1 2 / evens doubled, odds not
nines:+/s>9 / number of sums greater than 9
:~((+/s)-(9*nines))!10 / sum minus the nines is mod ten?
}
Example:
test:("49927398716";"49927398717";"1234567812345678";"1234567812345670")
luhn'test
1 0 0 1
[edit] Logo
to small? :list
output or [empty? :list] [empty? bf :list]
end
to every.other :list
if small? :list [output :list]
output fput first :list every.other bf bf :list
end
to wordtolist :word
output map.se [?] :word
end
to double.digit :digit
output item :digit {0 2 4 6 8 1 3 5 7 9}@0
; output ifelse :digit < 5 [2*:digit] [1 + modulo 2*:digit 10]
end
to luhn :credit
localmake "digits reverse filter [number? ?] wordtolist :credit
localmake "s1 apply "sum every.other :digits
localmake "s2 apply "sum map "double.digit every.other bf :digits
output equal? 0 last sum :s1 :s2
end
show luhn "49927398716 ; true
show luhn "49927398717 ; false
show luhn "1234-5678-1234-5678 ; false
show luhn "1234-5678-1234-5670 ; true
[edit] Liberty BASIC
' [RC] Luhn test
card$(1)="49927398716"
card$(2)="49927398717"
card$(3)="1234567812345678"
card$(4)="1234567812345670"
for test = 1 to 4
odd=1
sum = 0
for n = len(card$(test)) to 1 step -1
num=val(mid$(card$(test),n,1))
if odd then
sum = sum + num
odd=0
else
num=num*2
if num<=9 then
sum = sum + num
else
sum = sum + val(left$(str$(num),1)) + val(right$(str$(num),1))
end if
odd=1
end if
next
if sum mod 10 = 0 then
print card$(test),"True"
else
print card$(test),"False"
end if
next
[edit] Lua
function luhn(n)
n=string.reverse(n)
print(n)
local s1=0
--sum odd digits
for i=1,n:len(),2 do
s1=s1+n:sub(i,i)
end
--evens
local s2=0
for i=2,n:len(),2 do
local doubled=n:sub(i,i)*2
doubled=string.gsub(doubled,'(%d)(%d)',function(a,b)return a+b end)
s2=s2+doubled
end
print(s1)
print(s2)
local total=s1+s2
if total%10==0 then
return true
end
return false
end
-- Note that this function takes strings, not numbers.
-- 16-digit numbers tend to be problematic
-- when looking at individual digits.
print(luhn'49927398716')
print(luhn'49927398717')
print(luhn'1234567812345678')
print(luhn'1234567812345670')
[edit] Mathematica
LuhnQ[nb_] := (Mod[Total[(2*ToExpression[#[[2;;All;;2]]]) /. {z_?(Function[v, v>9]) -> z-9}]
+ Total[ToExpression[#[[1;;All;;2]]]], 10] == 0)& [Characters[StringReverse[ToString[nb]]] ]
LuhnQ /@ {49927398716, 49927398717, 1234567812345678, 1234567812345670}
->{True, False, False, True}
[edit] MATLAB
The solution for Octave will also work with Matlab.
There is no easy way to perform digit level manipulation of a number. In order to perform these digit level manipulations, many of the operations have to be performed on strings and char arrays. Using the built-in MATLAB string and numeral manipulation and conversion functions, it is possible to reduce the Luhn Algorithm to two lines of code. Unfortunately, because of the number of type conversions necessary to do this, these two lines of code are extremely obfuscated. The first example is the unobfuscated code. The second example is the vectorized version.
Example 1:
function passes = luhnTest(creditCardNum)
%flip the order of the digits
creditCardNum = fliplr( num2str(creditCardNum) )';
%sum the odd indexed digits
s1 = sum( str2num( creditCardNum(1:2:length(creditCardNum)) ) );
%multiply the even indexed digits by 2
s2 = 2 * str2num(creditCardNum(2:2:length(creditCardNum)));
%convert s2 into a cell array of strings, where each even indexed digit
%multiplied by 2 takes one cell in the cell array.
s2 = cellstr(num2str(s2));
%go through each cell in the cell array and make the strings a column
%array of chars
s2 = cellfun(@transpose,s2,'UniformOutput',false);
%convert each array of chars into an array of numbers
s2 = cellfun(@str2num ,s2,'UniformOutput',false);
%Sum the partial sums of the even indexed digits to form s2
s2 = sum( cellfun(@sum, s2));
%Convert the sum of s1 and s2 into a column vector with each digit of
%the the sum being an element of the vector
passes = str2num(num2str(s1+s2).');
%Find the smallest digit in the checksum, zero will only appear in the
%last digit of the number if zero is a digit of the checksum. Then
%convert the minimum digit to a boolean. Only zero will convert to a
%boolean false, any number larger than zero will convert to true.
%Therefore, because we want to determine if a credit card number passes
%the Luhn Test, we have to not the result of the conversion to boolean.
passes = ~logical(min(passes));
end
Example 2: (vectorized version of the above code)
function passes = luhnTest(creditCardNum)
%flip the order of the digits
creditCardNum = fliplr( num2str(creditCardNum) )';
%create the checksum and check its last digit for zero
passes = ~logical(min(str2num(num2str(sum( str2num( creditCardNum(1:2:length(creditCardNum)) ) )+sum( cellfun(@sum, cellfun(@str2num , cellfun(@transpose, cellstr(num2str(2*str2num(creditCardNum(2:2:length(creditCardNum))))) ,'UniformOutput',false) ,'UniformOutput',false)))).')));
end
This solution is guaranteed to work in older versions of MATLAB.
Due to the lack of function to change a number into a vector (e.g. 12=[1,2]) this function must be created first.
num2vec.m
function c=num2vec(a)
if a==0
c=0;
else
for i=1:100
if floor(a/(10^(i-1)))>0
n=i;
end
end
c=zeros(1,n);
b=zeros(1,n);
for i=1:n
b(i)=a/(10^(i-1));
b(i)=floor(b(i));
end
for i=1:n-1
b(i)=b(i)-(b(i+1)*10);
end
for i=1:n
c(i)=b(n-i+1);
end
end
luhn.m
function T=luhn(a)
a=num2vec(a);
N=length(a);
for i=1:N
b(i)=a(N+1-i);
end
for i=1:ceil(N/2)
c(i+1)=b(2*i-1);
end
s1=sum(c);
for i=1:floor(N/2)
d(i)=sum(num2vec(2*b(2*i)));
end
s2=sum(d);
T=s1+s2;
[edit] MUMPS
LUHN(C)
NEW ODD,EVEN,S
SET S=$REVERSE(C)
SET ODD=0 FOR I=1:2:$LENGTH(S) SET ODD=ODD+$EXTRACT(S,I)
SET EVEN=0 FOR I=2:2:$LENGTH(S) SET T=$EXTRACT(S,I)*2 SET EVEN=EVEN+$SELECT(T<=9:T,T>9:$EXTRACT(T,1)+$EXTRACT(T,2))
QUIT '((ODD+EVEN)#10)
USER>W !,$S($$LUHN^ROSETTA("49927398716")=0:"INVALID",1:"VALID")
VALID
USER>W !,$S($$LUHN^ROSETTA("49927398717")=0:"INVALID",1:"VALID")
INVALID
USER>W !,$S($$LUHN^ROSETTA("1234567812345678")=0:"INVALID",1:"VALID")
INVALID
USER>W !,$S($$LUHN^ROSETTA("1234567812345670")=0:"INVALID",1:"VALID")
VALID
[edit] NetRexx
class LuhnTest
method main(args=String[]) static
cc = 0
cc[1] = '49927398716'
cc[2] = '49927398717'
cc[3] = '1234567812345678'
cc[4] = '1234567812345670'
loop k=1 while cc[k] <> 0
r = checksum(cc[k])
if r==0 then say cc[k].right(20) 'passed'
else say cc[k].right(20) 'failed'
end
-- Luhn algorithm checksum for credit card numbers
method checksum(t) static
if t.length()//2 then t = '0't --pad # on left with 0
t = t.reverse()
s = 0
loop j = 1 to t.length()-1 by 2
q = 2*t.substr(j+1,1)
if q>9 then q = q.left(1) + q.right(1)
s= s+t.substr(j,1)+q
end
return s//10\==0
[edit] Objeck
bundle Default {
class Luhn {
function : IsValid(cc : String) ~ Bool {
isOdd := true;
oddSum := 0;
evenSum := 0;
for(i := cc->Size() - 1; i >= 0; i -= 1;) {
digit : Int := cc->Get(i) - '0';
if(isOdd) {
oddSum += digit;
}
else {
evenSum += digit / 5 + (2 * digit) % 10;
};
isOdd := isOdd <> true;
};
return (oddSum + evenSum) % 10 = 0;
}
function : Main(args : String[]) ~ Nil {
IsValid("49927398716")->PrintLine();
IsValid("49927398717")->PrintLine();
IsValid("1234567812345678")->PrintLine();
IsValid("1234567812345670")->PrintLine();
}
}
}
[edit] Objective-C
- (NSMutableArray *) toCharArray {
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[self length]];
for (int i=0; i < [self length]; i++) {
NSString *ichar = [NSString stringWithFormat:@"%c", [self characterAtIndex:i]];
[characters addObject:ichar];
}
return [characters autorelease];
}
+ (BOOL) luhnCheck:(NSString *)stringToTest {
NSMutableArray *stringAsChars = [stringToTest toCharArray];
BOOL isOdd = YES;
int oddSum = 0;
int evenSum = 0;
for (int i = [stringToTest length] - 1; i >= 0; i--) {
int digit = [(NSString *)[stringAsChars objectAtIndex:i] intValue];
if (isOdd)
oddSum += digit;
else
evenSum += digit/5 + (2*digit) % 10;
isOdd = !isOdd;
}
return ((oddSum + evenSum) % 10 == 0);
}
BOOL test0 = [self luhnCheck:@"49927398716"]; //Result = YES
BOOL test1 = [self luhnCheck:@"49927398717"]; //Result = NO
BOOL test2 = [self luhnCheck:@"1234567812345678"]; //Result = NO
BOOL test3 = [self luhnCheck:@"1234567812345670"]; //Result = YES
[edit] OCaml
let luhn s =
let rec g r c = function
| 0 -> r
| i ->
let d = c * ((int_of_char s.[i-1]) - 48) in
g (r + (d/10) + (d mod 10)) (3-c) (i-1)
in
(g 0 1 (String.length s)) mod 10 = 0
;;
Sample output
# List.map luhn [ "49927398716"; "49927398717"; "1234567812345678"; "1234567812345670" ];;
- : bool list = [true; false; false; true]
[edit] Octave
function y = isluhn(s);
if isnumeric(s) s = mat2str(s); end; % make sure s is a string
d = s-'0'; % convert string into vector of digits
m = [2:2:8,1:2:9]; % rule 3: maps [1:9] -> i
y = ~mod(sum(d(end:-2:1)) + sum(m(d(end-1:-2:1))),10);
end;
Sample output
isluhn('49927398716')
ans = 1
isluhn('49927398717')
ans = 0
isluhn('1234567812345678')
ans = 0
isluhn('1234567812345670')
ans = 1
[edit] Order
This example highlights Order's unusual treatment of numbers. Numbers larger than 100 are not recognized by the interpreter in literal form and must instead be entered as "native" numbers (i.e. listing the separate digits as arguments to 8nat). Since internally, a native number is just a sequence of the digits in reverse order with an end digit marker, converting the number into a reversed list of digits mainly involves removing this terminator, so that we can immediately treat the digits as number elements.
#include <order/interpreter.h>
#define ORDER_PP_DEF_8luhn ORDER_PP_FN( \
8fn(8N, 8if(8is_seq(8N), 8luhn_wk(8num_to_seq(8N)), 8false)) )
#define ORDER_PP_DEF_8num_to_seq ORDER_PP_FN( \
8fn(8N, 8seq_push_back(8seq(8seq_last(8N)), 8seq_pop_back(8N))) )
#define ORDER_PP_DEF_8luhn_wk ORDER_PP_FN( \
8fn(8N, \
8lets((8P, 8unzip(8N, 8nil, 8nil, 8true)) \
(8O, 8seq_fold(8plus, 0, 8tuple_at_0(8P))) \
(8E, 8seq_fold(8plus, 0, \
8seq_map(8dig_map, 8tuple_at_1(8P)))), \
8is_0(8remainder(8plus(8O, 8E), 10)))) )
#define ORDER_PP_DEF_8dig_map ORDER_PP_FN( \
8fn(8X, 8tuple_at(8X, 8tuple(0,2,4,6,8,1,3,5,7,9))) )
#define ORDER_PP_DEF_8unzip ORDER_PP_FN( \
8fn(8S, 8L, 8R, 8O, \
8if(8is_nil(8S), \
8pair(8L, 8R), \
8if(8O, \
8unzip(8seq_tail(8S), 8seq_push_back(8seq_head(8S), 8L), \
8R, 8false), \
8unzip(8seq_tail(8S), 8L, \
8seq_push_back(8seq_head(8S), 8R), 8true)))) )
ORDER_PP(8seq_to_tuple(
8seq_map(8luhn, 8seq(8nat(4,9,9,2,7,3,9,8,7,1,6),
8nat(4,9,9,2,7,3,9,8,7,1,7),
8nat(1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8),
8nat(1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,0)))
))
- Output:
(8true,8false,8false,8true)
[edit] Oz
declare
fun {Luhn N}
{Sum {List.mapInd {Reverse {Digits N}}
fun {$ Idx Dig}
if {IsEven Idx} then {Sum {Digits 2*Dig}}
else Dig
end
end}}
mod 10 == 0
end
fun {Digits N}
{Map {Int.toString N} fun {$ D} D - &0 end}
end
fun {Sum Xs}
{FoldL Xs Number.'+' 0}
end
in
{Show
{Map
[49927398716 49927398717 1234567812345678 1234567812345670]
Luhn}}
[edit] Pascal
program luhn;
function lunh(arg: string): boolean;
var
i, sum: integer;
temp: byte;
begin
sum := 0;
for i:= length(arg) downto 1 do begin // Run the characters backwards
temp := byte(arg[i])-48; // Convert from ASCII to byte
if (length(arg)-i) mod 2 = 0
then sum := sum + temp // Odd characters just add
else if temp < 5
then sum := sum + 2*temp // Even characters add double
else sum := sum + (2*temp)-9; // or sum the digits of the doubling
end;
result := sum mod 10 = 0; // Return true if sum ends in a 0
end;
begin
writeln(' 49927398716: ', lunh('49927398716'));
writeln(' 49927398717: ', lunh('49927398717'));
writeln('1234567812345678: ', lunh('1234567812345678'));
writeln('1234567812345670: ', lunh('1234567812345670'));
end.
Output:
49927398716: TRUE
49927398717: FALSE
1234567812345678: FALSE
1234567812345670: TRUE
[edit] Perl
sub validate
{
my @rev = reverse split //,$_[0];
my ($sum1,$sum2,$i) = (0,0,0);
for(my $i=0;$i<@rev;$i+=2)
{
$sum1 += $rev[$i];
last if $i == $#rev;
$sum2 += 2*$rev[$i+1]%10 + int(2*$rev[$i+1]/10);
}
return ($sum1+$sum2) % 10 == 0;
}
print validate('49927398716');
print validate('49927398717');
print validate('1234567812345678');
print validate('1234567812345670');
Or using map( ) and a precomputed array:
sub luhn {
my (@n,$i,$sum) = split //, reverse $_[0];
my @a = map {int(2*$_ / 10) + (2*$_ % 10)} (0..9);
map {$sum += $i++ % 2 ? $a[$_] : $_} @n;
return ($sum % 10) ? 0 : 1;
}
# Test and display
map {print luhn($_), ": $_\n"}
qw(49927398716 49927398717 1234567812345678 1234567812345670);
Output:
1: 49927398716 0: 49927398717 0: 1234567812345678 1: 1234567812345670
[edit] Perl 6
Here we make use of comb, which splits into individual characters, and the sequence operator ..., which can intuit an even or odd sequence from the first two values. The [+] is a reduction metaoperator; with + it just sums the list of values. %% is the divisible-by operator.
sub luhn-test ($cc-number --> Bool) {
my @digits = $cc-number.comb.reverse;
my $s1 = [+] @digits[0,2...@digits.end];
my $s2 = [+] @digits[1,3...@digits.end].map({[+] ($^a * 2).comb});
return ($s1 + $s2) %% 10;
}
And we can test it like this:
use Test;
my @cc-numbers =
'49927398716' => True,
'49927398717' => False,
'1234567812345678' => False,
'1234567812345670' => True;
plan @cc-numbers.elems;
for @cc-numbers».kv -> $cc, $expected-result {
is luhn-test($cc), $expected-result,
"$cc {$expected-result ?? 'passes' !! 'does not pass'} the Luhn test.";
}
Output:
1..4 ok 1 - 49927398716 passes the Luhn test. ok 2 - 49927398717 does not pass the Luhn test. ok 3 - 1234567812345678 does not pass the Luhn test. ok 4 - 1234567812345670 passes the Luhn test.
[edit] PHP
$numbers = "49927398716 49927398717 1234567812345678 1234567812345670";
foreach (split(' ', $numbers) as $n)
echo "$n is ", luhnTest($n) ? 'valid' : 'not valid', '</br>';
function luhnTest($num) {
$len = strlen($num);
for ($i = $len-1; $i >= 0; $i--) {
$ord = ord($num[$i]);
if (($len - 1) & $i) {
$sum += $ord;
} else {
$sum += $ord / 5 + (2 * $ord) % 10;
}
}
return $sum % 10 == 0;
}
49927398716 is valid 49927398717 is not valid 1234567812345678 is not valid 1234567812345670 is valid
And a more concise example using PHP core methods:
function luhn_test($num) {
$str = '';
foreach( array_reverse( str_split( $num ) ) as $i => $c ) $str .= ($i % 2 ? $c * 2 : $c );
return array_sum( str_split($str) ) % 10 == 0;
}
foreach (array('49927398716','49927398717','1234567812345678','1234567812345670') as $n)
echo "$n is ", luhn_test($n) ? 'valid' : 'not valid', "</br>\n";
49927398716 is valid 49927398717 is not valid 1234567812345678 is not valid 1234567812345670 is valid
[edit] PicoLisp
(de luhn (Num) # 'Num' may be a number or a string
(=0
(%
(sum
'((C F)
(setq C (- (char C) 48))
(if F
C # Odd
(+ (/ C 5) (% (* 2 C) 10)) ) ) # Even
(flip (chop Num))
'(T NIL .) )
10 ) ) )
Output:
: (mapcar luhn (49927398716 49927398717 1234567812345678 1234567812345670)) -> (0 NIL NIL 0)
[edit] PL/I
test: procedure options (main);
declare (cardnumber, rcn) character (20) varying;
declare (i, k, s1, s2) fixed binary;
get edit (cardnumber) (L);
cardnumber = trim(cardnumber);
rcn = reverse(cardnumber);
s1, s2 = 0;
/* Sum the odd-numbered digits */
do i = 1 to length(rcn) by 2;
s1 = s1 + substr(rcn, i, 1);
end;
/* Twice the even-numbered digits. */
do i = 2 to length(rcn) by 2;
k = 2 * substr(rcn, i, 1);
s2 = s2 + mod(k,10) + trunc(k/10);
end;
if mod(s1 + s2, 10) = 0 then
put skip edit (cardnumber, ' passes the Luhn test' )(a);
else
put skip edit (cardnumber, ' does not pass the Luhn test' )(a);
put skip list (s1 + s2);
end test;
Output:
49927398716 passes the Luhn test
70
49927398717 does not pass the Luhn test
71
1234567812345678 does not pass the Luhn test
68
1234567812345670 passes the Luhn test
60
Comment: it isn't necessary to reverse the string in order to perform the test.
[edit] PL/SQL
FUNCTION algoLuhn ( p_numeroVerif VARCHAR2 )
RETURN NUMBER
IS
i NUMBER;
v_NBi SMALLINT;
v_retour SMALLINT;
v_somme NUMBER := 0;
v_nbCar NUMBER;
BEGIN
v_nbCar := LENGTH(p_numeroVerif);
FOR i IN 1..v_nbCar
LOOP
v_NBi := TO_NUMBER(SUBSTR(p_numeroVerif,v_nbCar+1-i,1));
v_somme := v_somme
+ MOD(i,2) * v_NBi
+ MOD(i+1,2) * SIGN(-SIGN(v_Nbi-4)+1) * (2*v_NBi)
+ MOD(i+1,2) * SIGN( SIGN(v_Nbi-5)+1) * (2*v_NBi-9);
END LOOP;
v_retour := SIGN(MOD(v_somme,10));
RETURN v_retour;
EXCEPTION
WHEN OTHERS
THEN
RETURN 1;
END algoLuhn;
[edit] PureBasic
DataSection
Sample:
Data.s "49927398716"
Data.s "49927398717"
Data.s "1234567812345678"
Data.s "1234567812345670"
Data.s ""
EndDataSection
Procedure isValid(cardNumber.s)
Protected i, length, s1, s2, s2a
cardNumber = ReverseString(cardNumber)
length = Len(cardNumber)
For i = 1 To length Step 2
s1 + Val(Mid(cardNumber, i, 1))
Next
For i = 2 To length Step 2
s2a = Val(Mid(cardNumber, i, 1)) * 2
If s2a < 10
s2 + s2a
Else
s2 + 1 + Val(Right(Str(s2a), 1))
EndIf
Next
If Right(Str(s1 + s2), 1) = "0"
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
If OpenConsole()
Define cardNumber.s
Restore Sample
Repeat
Read.s cardNumber
If cardNumber <> ""
Print(cardNumber + " is ")
If isValid(cardNumber)
PrintN("valid")
Else
PrintN("not valid")
EndIf
EndIf
Until cardNumber = ""
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
EndIf
Sample output:
49927398716 is valid 49927398717 is not valid 1234567812345678 is not valid 1234567812345670 is valid
[edit] Python
The divmod in the function below conveniently splits a number into its two digits ready for summing:
>>> def luhn(n):
r = [int(ch) for ch in str(n)][::-1]
return (sum(r[0::2]) + sum(sum(divmod(d*2,10)) for d in r[1::2])) % 10 == 0
>>> for n in (49927398716, 49927398717, 1234567812345678, 1234567812345670):
print(n, luhn(n))
Sample output:
49927398716 True 49927398717 False 1234567812345678 False 1234567812345670 True
[edit] R
luhnTest <- function(cc){
# Reverse the digits, convert to numeric vector
cc2 <- as.numeric(unlist(strsplit(as.character(cc), "")))[nchar(cc):1]
s1 <- 0
s2 <- 0
for (index in 1:length(cc2)){
if (index %% 2 == 1){
s1 <- sum(s1, cc2[index])
} else if (cc2[index] >= 5){
s2 <- sum(s2, (cc2[index]*2 - 9))
} else {
s2 <- sum(s2, (cc2[index]*2))
}
}
return ((s1 + s2) %% 10 == 0)
}
Sample Output
sapply(c(49927398716, 49927398717, 1234567812345678, 1234567812345670), luhnTest)
[1] TRUE FALSE FALSE TRUE
[edit] Racket
#lang racket
(define (luhn-test n)
(let loop ([n n] [odd? #t] [s 0])
(if (zero? n)
(zero? (modulo s 10))
(let*-values ([(q r) (quotient/remainder n 10)]
[(rq rr) (quotient/remainder (* (if odd? 1 2) r) 10)])
(loop q (not odd?) (+ s rq rr))))))
(map luhn-test '(49927398716 49927398717 1234567812345678 1234567812345670))
;; -> '(#t #f #f #t)
[edit] REXX
[edit] version 1
/*REXX program to verify credit card numbers via the Luhn algorithm.*/
cc. = /*default value for the CC# list.*/
cc.1 = 49927398716 /*sample credit card number one. */
cc.2 = 49927398717 /* " " " " two. */
cc.3 = 1234567812345678 /* " " " " three*/
cc.4 = 1234567812345670 /* " " " " four.*/
@.0=' passed'; @.1="flunked"
do k=1 while cc.k\==''; retCode=LuhnChecksum(cc.k)
say right(cc.k, 30) @.retCode "the Luhn test."
end /*k*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────LUHNCHECKSUM subroutine─────────────*/
LuhnChecksum: procedure; parse arg t /*checksum for credit card nums. */
if length(t)//2 then t='0't /*odd #digs? Pad # on left with 0*/
t=reverse(t); s=0
do j=1 to length(t)-1 by 2; q=2*substr(t,j+1,1)
if q>9 then q=left(q,1) + right(q,1)
s=s + substr(t,j,1) + q
end /*j*/
return s//10\==0 /*returns: 0 (passed), 1 (failed)*/
output
49927398716 passed the Luhn test.
49927398717 flunked the Luhn test.
1234567812345678 flunked the Luhn test.
1234567812345670 passed the Luhn test.
[edit] Version 2
/* Rexx ***************************************************
* 09.04.2013 Walter Pachl
* Implements the task's description in a rather concise way
* Instead of reverting the ccn work it backwards
**********************************************************/
numeric digits 20
push 49927398716
push 49927398717
push 1234567812345678
push 1234567812345670
do while queued() > 0
parse pull ccnum
if luhn(ccnum) then ln = 'passed'
else ln = 'failed'
say right(ccnum, 20) ln
end
return
exit
luhn:
Parse Arg ccn /* credit card number */
sum=0 /* initialize test sum */
even=0 /* even indicator */
Do i=length(ccn) To 1 By -1 /* process all digits */
c=substr(ccn,i,1) /* pick one digit at a time */
If even Then Do /* even numbered digit */
c=c*2 /* double it */
If c>=10 Then /* 10, 12, 14, 16, 18 */
c=c-9 /* Sum of the two digits */
End /* end of even numbered */
even=\even /* flip even indicator */
sum=sum+c /* add into test sum */
End
Return right(sum,1)=0 /* ok if last digit is 0 */
- Output:
1234567812345670 passed
1234567812345678 failed
49927398717 failed
49927398716 passed
[edit] Ruby
def luhn(code)
s1 = s2 = 0
code.to_s.reverse.chars.each_slice(2) do |odd, even|
s1 += odd.to_i
double = even.to_i * 2
double -= 9 if double >= 10
s2 += double
end
(s1 + s2) % 10 == 0
end
[49927398716, 49927398717, 1234567812345678, 1234567812345670].each do |n|
p [n, luhn(n)]
end
outputs
[49927398716, true] [49927398717, false] [1234567812345678, false] [1234567812345670, true]
After implementing this for an interview question I decided to look around and see how my implementation compared performance wise to existing solutions. Here's an alternative implementation that's over twice as fast:
def luhn_perfomance_2_x_faster(i)
i = "#{i}"
index = i.length-1
ct = 1
sum = 0
while index > -1
i = i[index].to_i
if ct.even?
i = i * 2
if i > 9
tmp = "#{i}"
i = 0
tmp.each_char { |char|
i += char.to_i
}
end
end
sum += i
index -= 1
ct += 1
end
sum % 10 == 0
end
Benchmark measurements:
require 'benchmark'
puts "luhn measure: #{Benchmark.measure { 1000000.times { [49927398716, 49927398717, 1234567812345678, 1234567812345670].each { |i| luhn(i) }} }}"
puts "luhn_performance_2_x_faster measure: #{Benchmark.measure { 1000000.times { [49927398716, 49927398717, 1234567812345678, 1234567812345670].each { |i| luhn_perfomance_2_x_faster(i) }} }}"
luhn measure: 24.330000 0.010000 24.340000 ( 24.324950)
luhn_performance_2_x_faster measure: 11.190000 0.010000 11.200000 ( 11.191664)
[edit] Run BASIC
card$(1) = "49927398716"Output:
card$(2) = "49927398717"
card$(3) = "1234567812345678"
card$(4) = "1234567812345670"
for i = 1 to 4
print card$(i);" ";luhn$(card$(i))
next i
FUNCTION luhn$(card$)
lc = len(card$)
for i = lc to 1 step -1
digit = val(mid$(card$,i,1))
if ((lc -i) mod 2) = 0 then chkSum = chkSum + digit else chkSum = chkSum + int(digit * 2.2)
next i
if chkSum mod 10 = 0 then luhn$ = "True" else luhn$ = "False"
end function
49927398716 True 49927398717 False 1234567812345678 False 1234567812345670 True
[edit] Scala
Same method as used in C code
def luhnTest(number: String): Boolean = {
var odd = true
var sum = 0
for (int <- number.reverse.map{ i => i.toString.toInt }) {
if (odd)
sum = sum + int
else
sum = sum + (int * 2 % 10) + (int / 5)
odd = !odd
}
sum % 10 == 0
}
println(luhnTest("49927398716"))
println(luhnTest("49927398717"))
println(luhnTest("1234567812345678"))
println(luhnTest("1234567812345670"))
Sample output
true false false true
Alternatively, in a functional style:
def luhnTest(number: String): Boolean = {
val digits = number.reverse.map { _.toString.toInt }
val s = digits.grouped(2) map { t => t(0) +
(if (t.length > 1) (t(1) * 2) % 10 + t(1) / 5 else 0)
}
s.sum % 10 == 0
}
[edit] Scheme
(define luhn
(lambda (n)
(let loop ((number n)
(index 0)
(result 0))
(if (= 0 number)
(= 0 (remainder result 10))
(loop (quotient number 10)
(+ index 1)
(+ result
(if (even? index)
(remainder number 10)
(let ((part (* 2 (remainder number 10))))
(+ (remainder part 10) (quotient part 10))))))))))
(map luhn '(49927398716 49927398717 1234567812345678 1234567812345670)) (#t #f #f #t)
[edit] sed
# Split number into double evens and odds
s/.*/&: /
: split
s/\([0-4]\)\([0-9]\):\(.*\) /:\1\1\3 \2/
s/\([5-9]\)\([0-9]\):\(.*\) /:1\1\1\3 \2/
t split
# Set up addition lookup table
s/\([0-9]\)*:\(.*\) \(.*\)/\1\2\3:0123456789012345678/
: add
s/\([0-9]\)0:/\1:/
s/\([0-9]\)1:\(.*\1.\{0\}\([0-9]\).*\)/\3:\2/
s/\([0-9]\)2:\(.*\1.\{1\}\([0-9]\).*\)/\3:\2/
s/\([0-9]\)3:\(.*\1.\{2\}\([0-9]\).*\)/\3:\2/
s/\([0-9]\)4:\(.*\1.\{3\}\([0-9]\).*\)/\3:\2/
s/\([0-9]\)5:\(.*\1.\{4\}\([0-9]\).*\)/\3:\2/
s/\([0-9]\)6:\(.*\1.\{5\}\([0-9]\).*\)/\3:\2/
s/\([0-9]\)7:\(.*\1.\{6\}\([0-9]\).*\)/\3:\2/
s/\([0-9]\)8:\(.*\1.\{7\}\([0-9]\).*\)/\3:\2/
s/\([0-9]\)9:\(.*\1.\{8\}\([0-9]\).*\)/\3:\2/
t add
/0:/a\
Pass
/0:/!a\
Fail
d
sample Output
$ sed -f luhn.sed <<! 49927398716 49927398717 1234567812345678 1234567812345670 ! Pass Fail Fail Pass
[edit] Seed7
$ include "seed7_05.s7i";
const func boolean: luhnTest (in string: cardNumber) is func
result
var boolean: luhnTest is FALSE;
local
var integer: index is 0;
var integer: digit is 0;
var boolean: isOdd is TRUE;
var integer: oddSum is 0;
var integer: evenSum is 0;
begin
for index range length(cardNumber) downto 1 do
digit := integer parse str(cardNumber[index]);
if isOdd then
oddSum +:= digit;
else
evenSum +:= digit div 5 + (2 * digit) rem 10;
end if;
isOdd := not isOdd;
end for;
luhnTest := (oddSum + evenSum) rem 10 = 0;
end func;
const proc: main is func
local
var string: cardNumber is "";
begin
for cardNumber range [] ("49927398716", "49927398717", "1234567812345678", "1234567812345670") do
writeln(cardNumber <& ": " <& luhnTest(cardNumber));
end for;
end func;
Output:
49927398716: TRUE 49927398717: FALSE 1234567812345678: FALSE 1234567812345670: TRUE
[edit] SNOBOL4
Using a precomputed array.
define('luhn(n)a,d,i,j,sum') :(luhn_end)
luhn n = reverse(n); a = array('0:9')
ln1 a<i> = (2 * i / 10) + remdr(2 * i,10)
i = lt(i,9) i + 1 :s(ln1)
ln2 n len(1) . d = :f(ln3)
d = ne(remdr(j,2),0) a<d>; j = j + 1
sum = sum + d :(ln2)
ln3 luhn = 0; luhn = eq(remdr(sum,10),0) 1 :(return)
luhn_end
* # Test and display
test = " output = luhn(n) ': ' n"
n = '49927398716'; eval(test)
n = '49927398717'; eval(test)
n = '1234567812345678'; eval(test)
n = '1234567812345670'; eval(test)
end
Output:
1: 49927398716 0: 49927398717 0: 1234567812345678 1: 1234567812345670
[edit] SPARK
Works with SPARK GPL 2010 and GPS GPL 2010.
Based on the Ada version. All code shown to be free of run-time type errors.
A final test has been added which passes as valid unless there is an explicit test for all digits.
with Spark_IO;
--# inherit Spark_IO;
--# main_program;
procedure Luhn
--# global in out Spark_IO.Outputs;
--# derives Spark_IO.Outputs from *;
is
function Luhn_Test (Num : String) return Boolean
--# pre Num'Last <= 20;
is
Sum : Integer := 0;
Od : Boolean := True;
Int : Integer;
X : Integer;
OK : Boolean := True;
begin
for P in reverse Integer range Num'Range loop
Int := Character'Pos(Num(P)) - Character'Pos('0');
if Int not in 0 .. 9 then
OK := False;
exit;
end if;
X := (((Int*2) mod 10) + (Int / 5));
--# assert Num'Last - P in 0 .. 19
--# and Sum in 0 .. (Num'Last - P) * 10
--# and Int in 0 .. 9
--# and X in 0 .. 10;
if Od then
Sum := Sum + Int;
else
Sum := Sum + X;
end if;
Od := not Od;
end loop;
return OK and (Sum mod 10) = 0;
end Luhn_Test;
procedure Do_Test (Num : in String)
--# global in out Spark_IO.Outputs;
--# derives Spark_IO.Outputs from *, Num;
--# pre Num'Last <= 20;
is
begin
Spark_IO.Put_String(Spark_IO.Standard_Output, Num, 16);
if Luhn_Test(Num) then
Spark_IO.Put_String(Spark_IO.Standard_Output, " is valid.", 0);
else
Spark_IO.Put_String(Spark_IO.Standard_Output, " is not valid.", 0);
end if;
Spark_IO.New_Line(Spark_IO.Standard_Output, 1);
end Do_Test;
begin
Do_Test("49927398716");
Do_Test("49927398717");
Do_Test("1234567812345678");
Do_Test("1234567812345670");
Do_Test("123456781234567D");
end Luhn;
Output:
49927398716 is valid. 49927398717 is not valid. 1234567812345678 is not valid. 1234567812345670 is valid. 123456781234567D is not valid.
[edit] Tcl
Based on an algorithmic encoding for the test on Wikipedia.
package require Tcl 8.5
proc luhn digitString {
if {[regexp {[^0-9]} $digitString]} {error "not a number"}
set sum 0
set flip 1
foreach ch [lreverse [split $digitString {}]] {
incr sum [lindex {
{0 1 2 3 4 5 6 7 8 9}
{0 2 4 6 8 1 3 5 7 9}
} [expr {[incr flip] & 1}] $ch]
}
return [expr {($sum % 10) == 0}]
}
Driver:
foreach testNumber {
49927398716
49927398717
1234567812345678
1234567812345670
} {
puts [format "%s is %s" $testNumber \
[lindex {"NOT valid" "valid"} [luhn $testNumber]]]
}
Output:
49927398716 is valid 49927398717 is NOT valid 1234567812345678 is NOT valid 1234567812345670 is valid
[edit] TI-83 BASIC
PROGRAM:LUHN
:Disp "ENTER NUMBER"
:Input Str1
:0→S
:0→E
:For(I,length(Str1),1,-1)
:inString("0123456789",sub(Str1,I,1))–1→X
:If X<0
:Goto BA
:If E≠0
:Then
:2X→X
:If X>9
:X–9→X
:End
:X+S→S
:not(E)→E
:End
:If fPart(S/10)=0
:Then
:Disp "GOOD CARD"
:Else
:Lbl BA
:Disp "BAD CARD"
:End
[edit] TUSCRIPT
$$ MODE TUSCRIPT
MODE DATA
$$ SET cardnumbers=*
49927398716
49927398717
1234567812345678
1234567812345670
$$ MODE TUSCRIPT
-> collecting information for output-format
SET length=MAX_LENGTH(cardnumbers)
SET adjust=length+2
LOOP c=cardnumbers
-> ">/" = any digit
SET cstring=STRINGS (c,":>/:")
SET creverse=REVERSE (cstring)
SET s1=evenx2=esum=s2=""
LOOP n,oe=creverse
SET modrest=MOD(n,2)
IF (modrest==0) THEN
SET even=oe*2
IF (even>9) THEN
SET estring=STRINGS (even,":>/:")
SET esum=SUM (estring)
SET s2=APPEND (s2,esum)
ELSE
SET s2=APPEND (s2,even)
ENDIF
ELSE
SET s1=APPEND(s1,oe)
ENDIF
ENDLOOP
SET s1=SUM(s1),s2=SUM(s2)
SET checksum=s1+s2
SET c=CENTER(c,-adjust)
IF (checksum.ew."0") THEN
PRINT c,"true"
ELSE
PRINT c,"false"
ENDIF
ENDLOOP
Output:
49927398716 true 49927398717 false 1234567812345678 false 1234567812345670 true
[edit] TXR
@(do (defun luhn (num)
(for ((i 1) (sum 0))
((not (zerop num)) (zerop (mod sum 10)))
((inc i) (set num (trunc num 10)))
(let ((dig (mod num 10)))
(if (oddp i)
(inc sum dig)
(let ((dig2 (* 2 dig)))
(inc sum (+ (trunc dig2 10) (mod dig2 10)))))))))
@(collect :vars nil)
@{ccnumber /[0-9]+/}
@(output)
@ccnumber -> @(if (luhn (int-str ccnumber 10)) "good" "bad")
@(end)
@(end)
$ txr luhn.txr luhn.txt 49927398716 -> good 49927398717 -> bad 1234567812345678 -> bad 1234567812345670 -> good
[edit] Ursala
#import std
#import nat
luhn = %nP; %np*hxiNCNCS; not remainder\10+ //sum:-0@DrlrHK32 ~&iK27K28TK25 iota10
Some notes on this solution:
-
iota10is the list of natural numbers<0,1,2,3,4,5,6,7,8,9> -
~&K27and~&K28ofiota10extract the alternate items, respectively<0,2,4,6,8>and<1,3,5,7,9> -
~&K27K28T iota10is their concatenation,<0,2,4,6,8,1,3,5,7,9>which is also the list of values obtained by doubling each item ofiota10and taking digit sums -
~&iK27K28TX iota10would be the pair(<0,1,2,3,4,5,6,7,8,9>,<0,2,4,6,8,1,3,5,7,9>), but using the reification operatorK25in place ofXmakes it an executable function taking any item of the left list as an argument and returning the corresponding item of the right. - The part beginning with
//is a function of the form//f a, which can be applied to any argumentbto obtainf(a,b). In this case, thefissum:-0@DrlrHK32, which is equivalent to the composition of two functionssum:-0and~&DrlrHK32, andais the function just obtained by reification. - The function
~&Dby itself takes a pair(a,<b0...bn>)whose right side is a list, and returns the list of pairs<(a,b0)...(a,bn)>(i.e., a copy ofapaired with eachb). Theahere will end up being the aforementioned function. -
~&DrlrHK32not only forms such a list of pairs, but operates on each pair thus obtained, alternately applying~&rand~&lrHto each pair in sequence, where~&rsimply returns the right side of the pair, and~&lrHuses the left side as a function, which is applied to the right. -
sum:-0computes the cumulative sum of a list of natural numbers using the binarysumfunction, and the reduction operator (:-) with vacuous sum 0. - The whole thing described up to this point is therefore a function that will take a list of numbers in the range 0 to 9, and compute the summation obtained when doubling and digit summing alternate items.
- The input list to this function is constructed from a single natural number first by
%nP, which transforms it to text format in decimal, followed by%np*hxiNCNCS, which reverses the digits, makes a separate text of each, and parses them as individual numbers. - The output from the function is tested for divisibility by 10 with
remainder\10, with the result negated so that zero values map to true and non-zero to false.
usage:
#cast %bL
test = luhn* <49927398716,49927398717,1234567812345678,1234567812345670>
output:
<true,false,false,true>
[edit] ZX Spectrum Basic
10 LET c$="49927398716": GO SUB 1000
20 LET c$="49927398717": GO SUB 1000
30 LET c$="1234567812345678": GO SUB 1000
40 LET c$="1234567812345670": GO SUB 1000
999 STOP
1000 REM *************
1001 REM * LUHN TEST *
1002 REM *************
1010 LET r$=""
1020 FOR i=LEN c$ TO 1 STEP -1
1030 LET r$=r$+c$(i)
1040 NEXT i
1050 LET s1=0: LET s2=0
1060 FOR i=1 TO LEN r$ STEP 2
1070 LET s1=s1+VAL r$(i)
1080 NEXT i
1090 FOR i=2 TO LEN r$ STEP 2
1100 LET s2sub=VAL r$(i)*2
1110 IF s2sub>=10 THEN LET s2sub=1+s2sub-10
1120 LET s2=s2+s2sub
1130 NEXT i
1140 LET s$=STR$ (s1+s2)
1150 IF s$(LEN s$)="0" THEN PRINT c$;" VALID!": LET retval=1: RETURN
1160 PRINT c$;" INVALID!": LET retval=0: RETURN
Output:
49927398716 VALID! 49927398717 INVALID! 1234567812345678 INVALID! 1234567812345670 VALID!
[edit] Visual Basic .NET
Imports System.Linq
Function ValidLuhn(value As String)
Return value.Select(Function(c, i) (AscW(c) - 48) << ((value.Length - i - 1) And 1)).Sum(Function(n) If(n > 9, n - 9, n)) Mod 10 = 0
End Function
Sub Main()
Console.WriteLine(ValidLuhn("49927398716"))
Console.WriteLine(ValidLuhn("49927398717"))
Console.WriteLine(ValidLuhn("1234567812345678"))
Console.WriteLine(ValidLuhn("1234567812345670"))
End Sub
Output:
True False False True
- Programming Tasks
- Solutions by Programming Task
- ABAP
- ACL2
- ActionScript
- Ada
- ALGOL 68
- APL
- AutoHotkey
- AutoIt
- AWK
- Bash
- BBC BASIC
- Bracmat
- C
- C++
- C sharp
- Caché ObjectScript
- Clojure
- Common Lisp
- COBOL
- D
- Euphoria
- F Sharp
- Factor
- Forth
- Fortran
- GAP
- Go
- Groovy
- Haskell
- HicEst
- Icon
- Unicon
- J
- Java
- JavaScript
- K
- K3
- Logo
- Liberty BASIC
- Lua
- Mathematica
- MATLAB
- MATLAB examples needing attention
- Examples needing attention
- MUMPS
- NetRexx
- Objeck
- Objective-C
- OCaml
- Octave
- Order
- Oz
- Pascal
- Perl
- Perl 6
- PHP
- PicoLisp
- PL/I
- PL/SQL
- PureBasic
- Python
- R
- Racket
- REXX
- Ruby
- Run BASIC
- Scala
- Scheme
- Sed
- Seed7
- SNOBOL4
- SPARK
- Tcl
- TI-83 BASIC
- TUSCRIPT
- TXR
- Ursala
- ZX Spectrum Basic
- GUISS/Omit
- Visual Basic .NET