Luhn test of credit card numbers: Difference between revisions

m
 
(48 intermediate revisions by 29 users not shown)
Line 47:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">F luhn(n)
V ch = String(n)
V sum = 0
Line 64:
1234567812345678,
1234567812345670)
print(luhn(n))</langsyntaxhighlight>
 
{{out}}
Line 78:
For maximum compatibility, this program uses only the basic instruction set (S/360)
and an ASSIST macro (XPRNT) to keep the code as short as possible.
<langsyntaxhighlight lang="360asm">* Luhn test of credit card numbers 22/05/2016
LUHNTEST CSECT
USING LUHNTEST,R13 base register
Line 199:
PG DC CL80' ' buffer
YREGS
END LUHNTEST</langsyntaxhighlight>
{{out}}
<pre>
Line 209:
 
=={{header|8080 Assembly}}==
<langsyntaxhighlight lang="8080asm"> org 100h
jmp demo
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Line 269:
jmp 5
pass: db 'Pass$'
fail: db 'Fail$'</langsyntaxhighlight>
 
{{out}}
Line 284:
=={{header|8086 Assembly}}==
 
<langsyntaxhighlight lang="asm"> bits 16
cpu 8086
org 100h
Line 351:
section .data
pass: db 'Pass$'
fail: db 'Fail$'</langsyntaxhighlight>
 
{{out}}
Line 366:
 
=={{header|8th}}==
<syntaxhighlight lang="forth">
<lang Forth>
\ Adapted from the C version:
: remap \ n1 -- n2
Line 391:
"1234567812345670" test-luhn
 
bye</langsyntaxhighlight>
 
{{out}}
Line 403:
 
=={{header|ABAP}}==
<langsyntaxhighlight Abaplang="abap">METHOD luhn_check.
 
DATA: sum(1) TYPE n VALUE 0. " Sum of checksum.
Line 430:
ENDIF.
 
ENDMETHOD.</langsyntaxhighlight>
 
=={{header|ACL2}}==
<langsyntaxhighlight Lisplang="lisp">(include-book "arithmetic-3/top" :dir :system)
 
(defun digits (n)
Line 467:
(sum (double-and-sum-digits evens)))
10)
0)))</langsyntaxhighlight>
 
{{out}}
Line 478:
&gt; (luhn 1234567812345670)
T</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">PROC ReverseDigits(CHAR ARRAY n,rev)
BYTE i,j
 
i=n(0)
WHILE i>0 AND n(i)='0
DO
i==-1
OD
 
j=1
WHILE i>0
DO
rev(j)=n(i)
j==+1 i==-1
OD
rev(0)=j-1
RETURN
 
BYTE FUNC SumOddDigits(CHAR ARRAY n)
BYTE sum,i
 
sum=0
FOR i=1 TO n(0) STEP 2
DO
sum==+ValB(n(i))
OD
RETURN(sum)
 
BYTE FUNC SumEvenDigitsMultiplied(CHAR ARRAY n)
BYTE sum,i,v
 
sum=0
FOR i=2 TO n(0) STEP 2
DO
v=ValB(n(i))*2
IF v>9 THEN v==-9 FI
sum==+v
OD
RETURN(sum)
 
BYTE FUNC Luhn(CHAR ARRAY n)
CHAR ARRAY rev(20)
BYTE s1,s2
 
ReverseDigits(n,rev)
s1=SumOddDigits(rev)
s2=SumEvenDigitsMultiplied(rev)
 
IF (s1+s2) MOD 10=0 THEN
RETURN(1)
FI
RETURN(0)
PROC Test(CHAR ARRAY n)
PrintF("%S is ",n)
IF Luhn(n) THEN
PrintE("valid")
ELSE
PrintE("invalid")
FI
RETURN
 
PROC Main()
Test("49927398716")
Test("49927398717")
Test("1234567812345678")
Test("1234567812345670")
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Luhn_test_of_credit_card_numbers.png Screenshot from Atari 8-bit computer]
<pre>
49927398716 is valid
49927398717 is invalid
1234567812345678 is invalid
1234567812345670 is valid
</pre>
 
=={{header|ActionScript}}==
<langsyntaxhighlight ActionScriptlang="actionscript">function isValid(numString:String):Boolean
{
var isOdd:Boolean = true;
Line 499 ⟶ 577:
trace(isValid("49927398717"));
trace(isValid("1234567812345678"));
trace(isValid("1234567812345670"));</langsyntaxhighlight>
 
=={{header|Ada}}==
{{trans|C}}
{{works with|GNAT}}
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO;
use Ada.Text_IO;
 
Line 533 ⟶ 611:
Put_Line (Boolean'Image (Luhn_Test ("1234567812345670")));
 
end Luhn;</langsyntaxhighlight>
{{out}}
<pre>
Line 548 ⟶ 626:
 
{{works with|ELLA ALGOL 68|Any (with appropriate job cards)}}
<langsyntaxhighlight lang="algol68">PROC to int = (CHAR c)INT:
ABS c - ABS "0";
Line 581 ⟶ 659:
print((cp, ": ", confirm(cp), new line))
OD
)</langsyntaxhighlight>
{{out}}
<pre>
Line 592 ⟶ 670:
=={{header|ALGOL W}}==
Separate source so the LuhnTest procedure can be used in other tasks, e.g.: [[Validate International Securities Identification Number]]
<langsyntaxhighlight lang="algolw">% returns true if ccNumber passes the Luhn test, false otherwise %
% as Algol W has fixed length strings, the length of the number %
% must be specified in ccLength %
Line 616 ⟶ 694:
end for_cPos ;
isValid and ( ( checkSum rem 10 ) = 0 )
end LuhnTest</langsyntaxhighlight>
 
Use the above to test the LuhnTest procedure:
 
<langsyntaxhighlight lang="algolw">begin
% external procedure that returns true if ccNumber passes the Luhn test, false otherwise %
logical procedure LuhnTest ( string(32) value ccNumber
Line 639 ⟶ 717:
testLuhnTest( "1234567812345670", 16 )
 
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 650 ⟶ 728:
=={{header|APL}}==
{{works with|Dyalog APL}}
<langsyntaxhighlight APLlang="apl">LuhnTest←{
digits←⍎¨⍵ ⍝ Characters to digits
doubled←2∘×@(⌽⍤~1 0⍴⍨≢)⊢digits ⍝ Double every other digit
partial←-∘9@(9∘<)⊢doubled ⍝ Subtract 9 is equivalent to sum of digits for the domain 10≤x≤19
0=10|+/partial ⍝ Valid if sum is a multiple of 10
}</langsyntaxhighlight>
{{out}}
<pre>
Line 663 ⟶ 741:
 
{{works with|APL+Win}}
<langsyntaxhighlight APLlang="apl"> ∇ 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
∇</langsyntaxhighlight>
{{out}}
<pre> LuhnTest¨ 49927398716 49927398717 1234567812345678 1234567812345670
Line 676 ⟶ 754:
=={{header|AppleScript}}==
===Functional===
<langsyntaxhighlight lang="applescript">-- luhn :: String -> Bool
on luhn(s)
-- True if the digit string represents
Line 839 ⟶ 917:
return lst
end tell
end zipWith</langsyntaxhighlight>
{{Out}}
<pre>{true, false, false, true}</pre>
Line 845 ⟶ 923:
===Straightforward===
 
<langsyntaxhighlight lang="applescript">on luhnTest(n)
-- Accept only text input.
if (n's class is not text) then return false
Line 879 ⟶ 957:
set end of testResults to {testNumber:testNumber's contents, valid:luhnTest(testNumber)}
end repeat
return testResults</langsyntaxhighlight>
 
{{output}}
<langsyntaxhighlight lang="applescript">{{testNumber:"49927398716", valid:true}, {testNumber:"49927398717", valid:false}, {testNumber:"1234567812345678", valid:false}, {testNumber:"1234567812345670", valid:true}}</langsyntaxhighlight>
 
=={{header|ARM Assembly}}==
<syntaxhighlight lang="arm_assembly">.text
<lang ARM_Assembly>.text
.global _start
_start:
Line 1,058 ⟶ 1,136:
.asciz "49927398717"
.asciz "1234567812345678"
.asciz "1234567812345670" </langsyntaxhighlight>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">digits: function [n][
res: new []
while -> n > 0 [
'res ++ n % 10
n: n / 10
]
res
]
 
luhn?: function [n][
s1: new 0
s2: new 0
loop.with: 'i digits n 'd [
if? even? i -> 's1 + d
else [
'd * 2
if d > 9 -> 'd - 9
's2 + d
]
]
zero? (s1 + s2) % 10
]
 
print luhn? 49927398716
print luhn? 49927398717
print luhn? 1234567812345678
print luhn? 1234567812345670
</syntaxhighlight>
 
{{out}}
 
<pre>true
false
false
true</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">; Originally submitted by Laszlo:
; http://www.autohotkey.com/forum/post-229412.html#229412
 
Line 1,079 ⟶ 1,195:
Sum += ( ( 9 < ( Temp := MultFactor * A_LoopField ) ) ? Temp - 9 : Temp ) , MultFactor := 3 - MultFactor
Return !Mod(Sum,10)
}</langsyntaxhighlight>
 
=={{header|AutoIt}}==
<syntaxhighlight lang="autoit">
<lang AutoIt>
Global $avarray[4] = [49927398716, 49927398717, 1234567812345678, 1234567812345670]
For $i = 0 To 3
Line 1,106 ⟶ 1,222:
EndIf
EndFunc ;==>checkLuhn
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,115 ⟶ 1,231:
 
=={{header|AWK}}==
<langsyntaxhighlight lang="awk">#!/usr/bin/awk -f
BEGIN {
A[1] = 49927398716;
Line 1,138 ⟶ 1,254:
}
return ((s%10)==0);
}</langsyntaxhighlight>
{{out}}
<pre>isLuhn(1234567812345670): 1
Line 1,149 ⟶ 1,265:
 
=={{header|Bash}}==
<langsyntaxhighlight lang="bash">#!/bin/bash
 
function luhn_validate # <numeric-string>
Line 1,188 ⟶ 1,304:
print_result "49927398717"
print_result "1234567812345678"
print_result "1234567812345670"</langsyntaxhighlight>
 
{{out}}
Line 1,196 ⟶ 1,312:
1234567812345670 is valid
</pre>
 
=={{header|BASIC}}==
==={{header|BASIC256}}===
<syntaxhighlight lang="freebasic">dim card$(5)
card$[1]="49927398716"
card$[2]="49927398717"
card$[3]="1234567812345678"
card$[4]="1234567812345670"
 
for test = 1 to 4
odd = True
sum = 0
for n = length(card$[test]) to 1 step -1
num = int(mid(card$[test],n,1))
if odd then
sum += num
odd = False
else
num *= 2
if num <= 9 then
sum += num
else
sum += int(left(string(num),1)) + int(right(string(num),1))
end if
odd = True
end if
next
if sum mod 10 = 0 then
print card$[test], "True"
else
print card$[test], "False"
end if
next test</syntaxhighlight>
 
==={{header|Chipmunk Basic}}===
{{works with|Chipmunk Basic|3.6.4}}
<syntaxhighlight lang="qbasic">100 cls
110 rem Luhn test
120 dim card$(5)
130 card$(1) = "49927398716"
140 card$(2) = "49927398717"
150 card$(3) = "1234567812345678"
160 card$(4) = "1234567812345670"
170 for test = 1 to 4
180 odd = true
190 sum = 0
200 for n = len(card$(test)) to 1 step -1
210 num = val(mid$(card$(test),n,1))
220 if odd then
230 sum = sum+num
240 odd = false
250 else
260 num = num*2
270 if num <= 9 then
280 sum = sum+num
290 else
300 sum = sum+val(left$(str$(num),1))+val(right$(str$(num),1))
310 endif
320 odd = true
330 endif
340 next
350 if sum mod 10 = 0 then
360 print card$(test),"True"
370 else
380 print card$(test),"False"
390 endif
400 next test</syntaxhighlight>
 
==={{header|IS-BASIC}}===
<syntaxhighlight lang="is-basic">100 PROGRAM "CredCard.bas"
110 DO
120 PRINT :PRINT "Credit card number:":INPUT PROMPT ">":CCN$
130 IF CCN$="" THEN EXIT DO
140 IF LUHN(TRIM$(CCN$)) THEN
150 PRINT "Card number is valid."
160 ELSE
170 SET #102:INK 3:PRINT "Card number is invalid.":SET #102:INK 1
180 END IF
190 LOOP
200 DEF LUHN(CCN$)
210 LET L=LEN(CCN$):LET S=0
220 FOR I=1 TO L
230 LET N=VAL(CCN$(L-I+1))
240 IF I BAND 1 THEN
250 LET S=S+N
260 ELSE
270 LET N=N*2:LET S=S+MOD(N,10)+INT(N/10)
280 END IF
290 NEXT
300 LET LUHN=MOD(S,10)=0
310 END DEF
320 DEF TRIM$(S$)
330 LET T$=""
340 FOR I=1 TO LEN(S$)
350 IF S$(I)>CHR$(47) AND S$(I)<CHR$(58) THEN LET T$=T$&S$(I)
360 NEXT
370 LET TRIM$=T$
380 END DEF</syntaxhighlight>
 
Output:
<pre>Credit card number:
>49927398716
Card number is valid.
 
Credit card number:
>49927398717
Card number is invalid.
 
Credit card number:
>1234 5678 1234 5678
Card number is invalid.
 
Credit card number:
>1234 5678 1234 5670
Card number is valid.</pre>
 
==={{header|QBasic}}===
{{works with|QBasic|1.1}}
{{works with|QuickBasic|4.5}}
<syntaxhighlight lang="qbasic">CONST True = -1: False = NOT True
 
DIM card$(5)
card$(1) = "49927398716"
card$(2) = "49927398717"
card$(3) = "1234567812345678"
card$(4) = "1234567812345670"
 
FOR test = 1 TO 4
odd = True
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 = False
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 = True
END IF
NEXT
IF sum MOD 10 = 0 THEN
PRINT card$(test), "True"
ELSE
PRINT card$(test), "False"
END IF
NEXT test</syntaxhighlight>
 
==={{header|True BASIC}}===
<syntaxhighlight lang="qbasic">LET true = -1
LET false = 0
 
DIM card$(5)
LET card$(1) = "49927398716"
LET card$(2) = "49927398717"
LET card$(3) = "1234567812345678"
LET card$(4) = "1234567812345670"
 
FOR test = 1 TO 4
LET odd = true
LET sum = 0
FOR n = LEN(card$(test)) TO 1 STEP -1
LET num = VAL((card$(test))[n:n+1-1])
IF odd<>0 THEN
LET sum = sum + num
LET odd = false
ELSE
LET num = num*2
IF num <= 9 THEN
LET sum = sum + num
ELSE
LET sum = sum + VAL((STR$(num))[1:1]) + VAL((STR$(num))[LEN(STR$(num))-1+1:maxnum])
END IF
LET odd = true
END IF
NEXT n
IF remainder(round(sum),10) = 0 THEN PRINT card$(test), "True" ELSE PRINT card$(test), "False"
NEXT test
END</syntaxhighlight>
 
==={{header|uBasic/4tH}}===
{{Trans|C}}
<syntaxhighlight lang="qbasic">Print " 49927398716", Show (Iif(FUNC(_Luhn ("49927398716")), "ok", "fail"))
Print " 49927398717", Show (Iif(FUNC(_Luhn ("49927398717")), "ok", "fail"))
Print "1234567812345678", Show (Iif(FUNC(_Luhn ("1234567812345678")), "ok", "fail"))
Print "1234567812345670", Show (Iif(FUNC(_Luhn ("1234567812345670")), "ok", "fail"))
End
 
_Luhn
Param (1)
Local (4)
 
c@ = 1 : d@ = 0
 
For b@ = Len(a@)-1 To 0 Step -1
e@ = Peek(a@, b@) - Ord("0")
d@ = d@ + Iif (c@, e@, e@+e@-9*(e@>4))
c@ = c@ = 0
Next
 
Return ((d@ % 10) = 0)
</syntaxhighlight>
{{Out}}
<pre> 49927398716 ok
49927398717 fail
1234567812345678 fail
1234567812345670 ok
 
0 OK, 0:333</pre>
 
==={{header|Yabasic}}===
<syntaxhighlight lang="yabasic">dim card$(5)
card$(1)="49927398716"
card$(2)="49927398717"
card$(3)="1234567812345678"
card$(4)="1234567812345670"
 
for test = 1 to 4
odd = true
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 = false
else
num = num * 2
if num <= 9 then
sum = sum + num
else
sum = sum + val(left$(str$(num),1)) + val(right$(str$(num),1))
fi
odd = true
fi
next
if mod(sum, 10) = 0 then
print card$(test), chr$(9), "True"
else
print card$(test), chr$(9), "False"
fi
next test</syntaxhighlight>
 
=={{header|Batch File}}==
This simple implementation does not reverse the numbers. Instead, it counts from right to left.
<langsyntaxhighlight lang="dos">@echo off
setlocal enabledelayedexpansion
 
call :luhn 49927398716
call :luhn 49927398717
Line 1,207 ⟶ 1,568:
call :luhn 1234567812345670
exit /b 0
 
:luhn
set "input=%1"
set "cnt=0"
set "s1=0&set s2=0"
set "s2=0"
:digit_loop
set /a "cnt-=1"
set /a "isOdd=^(-%cnt%^)%%2"
 
if !isodd! equ 1 (
set /a "s1+=!input:~%cnt%,1!"
) else (
set /a "twice=!input:~%cnt%,1!*2"
if !twice! geq 10 (
set /a "s2+=!twice:~0,1!+!twice:~1,1!"
) else (
set /a twice"s2+=!input:~%cnt%,1twice!*2"
if !twice! geq 10 (
set /a s2+=!twice:~0,1!+!twice:~1,1!
) else (
set /a s2+=!twice!
)
)
)
if "!input:~%cnt%!"=="!input!" (
if "!input:~%cnt%!"=="!input!" (
set /a sum=^(!s1!+!s2!^)%%10
set /a "sum=(!s1!+!s2!)%%10"
if !sum! equ 0 (echo !input! is valid.) else (echo !input! is not valid.)
if !sum! equ 0 (echo !input! is valid.) else (echo !input! is not valid.)
goto :EOF
goto :EOF
)
)
goto digit_loop</lang>
goto digit_loop</syntaxhighlight>
{{Out}}
<pre>>luhn.bat
Line 1,242 ⟶ 1,604:
 
=={{header|BBC BASIC}}==
<langsyntaxhighlight lang="bbcbasic"> FOR card% = 1 TO 4
READ cardnumber$
IF FNluhn(cardnumber$) THEN
Line 1,266 ⟶ 1,628:
ENDIF
NEXT
= (S% MOD 10) = 0</langsyntaxhighlight>
 
=={{header|bc}}==
<langsyntaxhighlight lang="bc">/* Return 1 if number passes Luhn test, else 0 */
define l(n) {
auto m, o, s, x
Line 1,294 ⟶ 1,656:
l(49927398717)
l(1234567812345678)
l(1234567812345670)</langsyntaxhighlight>
 
{{Out}}
Line 1,301 ⟶ 1,663:
0
1</pre>
 
=={{header|BCPL}}==
<syntaxhighlight lang="bcpl">get "libhdr"
 
let luhn(s) = valof
$( let sum=0 and fac=1
for i = s%0 to 1 by -1
$( unless '0' <= s%i <= '9' resultis false
sum := sum + fac*(s%i - '0') rem 10 + fac*(s%i - '0')/10
fac := 3 - fac
$)
resultis sum rem 10 = 0
$)
 
let show(s) be
writef("%S: %S*N", s, luhn(s) -> "pass", "fail")
 
let start() be
$( show("49927398716")
show("49927398717")
show("1234567812345678")
show("1234567812345670")
$)</syntaxhighlight>
{{out}}
<pre>49927398716: pass
49927398717: fail
1234567812345678: fail
1234567812345670: pass</pre>
 
=={{header|Befunge}}==
 
<langsyntaxhighlight lang="befunge">v 1 >$0 v v <
>&:19+`|v < >v 5 6 7 8
^ \ <>09p19p>09g+09p:|>2*:19+%19g+19p19+/19g+19p:|
Line 1,313 ⟶ 1,703:
>:#,_@
11
</syntaxhighlight>
</lang>
The labelled points (1 to 11) are:
1. Read in input until number greater than 10,
Line 1,344 ⟶ 1,734:
valid
</pre>
 
=={{header|BQN}}==
<syntaxhighlight lang="bqn">Luhn ← (0=10|⊢)∘(+´(10|⊢)+⊢≥10˙)∘(⊢×≠⥊1‿2˙)∘(⌽•Fmt-'0'˙)
 
(⍉⊢≍Luhn¨) ⟨49927398716,49927398717,1234567812345678,1234567812345670⟩</syntaxhighlight>
{{out}}
<pre>┌─
╵ 49927398716 1
49927398717 0
1234567812345678 0
1234567812345670 1
┘</pre>
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat"> ( luhn
= sum odd even
. 0:?sum
Line 1,370 ⟶ 1,772:
& test$1234567812345678
& test$1234567812345670
& ;</langsyntaxhighlight>
{{out}}
<pre>49927398716 : true
Line 1,379 ⟶ 1,781:
=={{header|Brainf***}}==
 
<syntaxhighlight lang="text">>>>>>>>>>+>,----------[ READ CHARACTERS UNTIL \N AND
>++++++++[<----->-]<++>>>>>>+>,----------] SUBTRACT ASCII 0 FROM EACH
<-<<<<<<< GO TO LAST DIGIT
Line 1,413 ⟶ 1,815:
<[<<.<---.<+++++..<] IF ZERO PASS
++++++++++. NEWLINE
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,426 ⟶ 1,828:
Pass</pre>
 
=={{header|Bruijn}}==
<syntaxhighlight lang="bruijn">
:import std/Combinator .
:import std/Math .
:import std/List .
 
luhn number→list → reverse → check → (\mod (+10)) → zero?
check y [[[[0 [[[6 \5 (4 + (5 odd even)) 1]]] 1]]]] k (+0)
odd 2
even digit-sum (2 ⋅ (+2))
 
:test (luhn (+61789372994)) ([[1]])
:test (luhn (+49927398716)) ([[1]])
:test (luhn (+49927398717)) ([[0]])
:test (luhn (+1234567812345678)) ([[0]])
:test (luhn (+1234567812345670)) ([[1]])
</syntaxhighlight>
 
=={{header|Burlesque}}==
 
<syntaxhighlight lang="text">
tt "Remove whitespace"vv
pe "Eval to number"vv
<- "Reverse digits"vv
XX "Split number into digits"vv
 
{
{ "Odd digits"vv
2EN
}
{ "Even digits"vv
2en
{
2.* "Double"vv
^^ 9.> "<test>=Duplicate greater than 9"vv
{
XX++ "Sum digits"vv
}if "If <test>"vv
}m[ "For each even digit"vv
}
}M- "Cool map. Create array of each branch applied to argument."vv
 
{++}m[ "Sum each block (odd & even)"vv
++ "Sum these"vv
[- "Last digit"vv
0== "Equal to zero"vv
Q "Pretty print"vv
</syntaxhighlight>
 
{{out}}
49927398716 1
49927398717 0
1234567812345678 0
1234567812345670 1
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <string.h>
#include <stdio.h>
 
Line 1,459 ⟶ 1,916:
 
return 0;
}</langsyntaxhighlight>{{out}}
49927398716 ok
49927398717 not ok
Line 1,469 ⟶ 1,926:
The LuhnCheck method takes an array of integers because values in memory will be integer-aligned.
 
<langsyntaxhighlight lang="csharp">
public static class Luhn
{
Line 1,497 ⟶ 1,954:
}
}
</syntaxhighlight>
</lang>
<pre>
49927398716 is valid
Line 1,507 ⟶ 1,964:
Note that the original implementation, which follows, is flawed because it assumes that n is a number which, when represented as a string, has an even number of characters. Granted, the brief is for Credit Card Numbers which are all, at the time of writing, an even number of digits.
 
<langsyntaxhighlight lang="csharp">using System;
using System.Linq;
 
Line 1,550 ⟶ 2,007:
}
}
}</langsyntaxhighlight>
<pre>
49927398716 is valid
Line 1,559 ⟶ 2,016:
 
A solution without using LINQ, works for all versions of .NET.
<langsyntaxhighlight lang="csharp">
using System;
namespace Luhn_Test
Line 1,610 ⟶ 2,067:
}
}
</syntaxhighlight>
</lang>
<pre>
1234567812345670 is Valid.
Line 1,619 ⟶ 2,076:
 
A solution optimized for readability:
<langsyntaxhighlight lang="csharp">
using System;
using System.Linq;
Line 1,642 ⟶ 2,099:
}
}
</syntaxhighlight>
</lang>
 
Extremely compact version uses Europa rtl library https://github.com/CodeAlkemist/Europa-rtl
<langsyntaxhighlight lang="csharp">
using System;
using EuropaRTL.Utilities;
Line 1,676 ⟶ 2,133:
}
}
</syntaxhighlight>
</lang>
<pre>
49927398716
Line 1,689 ⟶ 2,146:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
using namespace std;
 
Line 1,731 ⟶ 2,188:
}
return 0;
}</langsyntaxhighlight>
 
===C++11===
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <vector>
#include <algorithm>
Line 1,755 ⟶ 2,212:
return 0;
}
</syntaxhighlight>
</lang>
 
It is also possible to achieve a compile-time version using metaprogramming.
 
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <type_traits>
 
Line 1,853 ⟶ 2,310:
return 0;
}
</syntaxhighlight>
</lang>
<pre>
true
Line 1,863 ⟶ 2,320:
=={{header|Caché ObjectScript}}==
 
<langsyntaxhighlight lang="cos">Class Utils.Check [ Abstract ]
{
 
Line 1,879 ⟶ 2,336:
}
 
}</langsyntaxhighlight>
{{out|Examples}}
<pre>USER>For { Read ccn Quit:ccn="" Write ": "_##class(Utils.Check).Luhn(ccn), ! }
Line 1,890 ⟶ 2,347:
 
=={{header|Ceylon}}==
<langsyntaxhighlight lang="ceylon">shared void run() {
value numbers = "49927398716
49927398717
Line 1,916 ⟶ 2,373:
};
return (s1 + s2) % 10 == 0;
}</langsyntaxhighlight>
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(defn luhn? [cc]
(let [factors (cycle [1 2])
numbers (map #(Character/digit % 10) cc)
Line 1,927 ⟶ 2,384:
 
(doseq [n ["49927398716" "49927398717" "1234567812345678" "1234567812345670"]]
(println (luhn? n)))</langsyntaxhighlight>
 
=={{header|CLU}}==
<syntaxhighlight lang="clu">luhn = proc (num: string) returns (bool) signals (bad_format)
total: int := 0
even: bool := true
for i: int in int$from_to_by(string$size(num), 1, -1) do
digit: int := int$parse(string$c2s(num[i])) resignal bad_format
even := ~even
if even then
digit := 2 * digit
if digit >= 10 then digit := digit//10 + 1 end
end
total := total + digit
end
return(total // 10 = 0)
end luhn
 
start_up = proc ()
po: stream := stream$primary_output()
tests: sequence[string] := sequence[string]$
["49927398716", "49927398717", "1234567812345678", "1234567812345670"]
for test: string in sequence[string]$elements(tests) do
stream$puts(po, test || ": ")
if luhn(test)
then stream$putl(po, "pass")
else stream$putl(po, "fail")
end
end
end start_up</syntaxhighlight>
{{out}}
<pre>49927398716: pass
49927398717: fail
1234567812345678: fail
1234567812345670: pass</pre>
 
=={{header|COBOL}}==
{{works with|OpenCOBOL}}
{{works with|IBM Enterprise COBOL for z/OS}}
<langsyntaxhighlight lang="cobol"> IDENTIFICATION DIVISION.
PROGRAM-ID. LUHNTEST.
ENVIRONMENT DIVISION.
Line 2,018 ⟶ 2,509:
goback
.
END PROGRAM LUHN.</langsyntaxhighlight>
 
{{out}}
Line 2,027 ⟶ 2,518:
input=1234567812345670 pass
</pre>
 
=={{header|Comal}}==
<syntaxhighlight lang="comal">0010 FUNC luhn(s$) CLOSED
0020 total#:=0
0030 even#:=TRUE
0040 FOR i#:=LEN(s$) TO 1 STEP -1 DO
0050 digit#:=VAL(s$(i#))
0060 even#:=NOT even#
0070 IF even# THEN digit#:=(2*digit#) DIV 10+(2*digit#) MOD 10
0080 total#:+digit#
0090 ENDFOR i#
0100 RETURN total# MOD 10=0
0110 ENDFUNC luhn
0120 //
0130 PROC test(s$)
0140 PRINT s$,": ",
0150 IF luhn(s$) THEN
0160 PRINT "pass"
0170 ELSE
0180 PRINT "fail"
0190 ENDIF
0200 ENDPROC test
0210 //
0220 test("49927398716")
0230 test("49927398717")
0240 test("1234567812345678")
0250 test("1234567812345670")
0260 END</syntaxhighlight>
{{out}}
<pre>49927398716: pass
49927398717: fail
1234567812345678: fail
1234567812345670: pass</pre>
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun luhn (n)
(labels ((sum-digits (n) (if (> n 9) (- n 9) n)))
(let ((n* (reverse n)) (l (length n)))
Line 2,036 ⟶ 2,560:
(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))))))</langsyntaxhighlight>
Another version, using Maciej Pasternacki's reader macros for
function composition and [[currying]] in the [http://www.cl-user.net/asp/Fr4F/sdataQ1nAQqjvnQ3MDQ3ESH8X8yBX8yBXnMq=/sdataQu3F$sSHnB== curly] package:
<langsyntaxhighlight lang="lisp">(require :curly)
(use-package :curly)
(enable-curly-syntax)
Line 2,046 ⟶ 2,570:
(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)))</langsyntaxhighlight>
 
=={{header|Cowgol}}==
<langsyntaxhighlight lang="cowgol">include "cowgol.coh";
 
# Given a string containing the digits of a credit card number,
Line 2,110 ⟶ 2,634:
test("49927398717");
test("1234567812345678");
test("1234567812345670");</langsyntaxhighlight>
 
{{out}}
Line 2,119 ⟶ 2,643:
 
=={{header|Crystal}}==
<langsyntaxhighlight lang="ruby">def luhn_valid?(n) # Card values can be numbers or strings
d2sum = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
sum, n = 0, n.to_u64
Line 2,127 ⟶ 2,651:
 
cards = [49927398716, "49927398717", 1234567812345678, "1234567812345670"]
cards.each{ |i| puts "#{i}: #{luhn_valid?(i)}" }</langsyntaxhighlight>
{{out}}
<pre>49927398716: true
Line 2,137 ⟶ 2,661:
===Functional Version===
{{trans|Haskell}}
<langsyntaxhighlight lang="d">import std.algorithm, std.range, std.string;
 
enum luhnTest = (in string n) pure /*nothrow*/ @safe /*@nogc*/ =>
Line 2,149 ⟶ 2,673:
assert("49927398716 49927398717 1234567812345678 1234567812345670"
.split.map!luhnTest.equal([true, false, false, true]));
}</langsyntaxhighlight>
 
===More Imperative Version===
{{trans|C}}
<langsyntaxhighlight lang="d">import std.algorithm;
 
bool luhnTest(in string num) @safe pure nothrow @nogc {
Line 2,170 ⟶ 2,694:
"1234567812345670"];
assert(data.map!luhnTest.equal([true, false, false, true]));
}</langsyntaxhighlight>
 
===Stronger Statically Typed Version===
This version uses more precise types.
{{trans|SPARK}}
<langsyntaxhighlight lang="d">import std.stdio;
 
struct Interval(T) {
Line 2,234 ⟶ 2,758:
"123456781234567D"])
writefln("%s is %svalid", n, luhnTest(n) ? "" : "not ");
}</langsyntaxhighlight>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
Uses an array to handle the situation where multiply a term by 2, creates a two digit number. The array automatically handles adding each digit of the resulting two digit number. Also, avoids reversing the number by traversing the array backwards
 
<syntaxhighlight lang="Delphi">
{Test data arrays}
 
const Num1: array [0..10] of byte = (4,9,9,2,7,3,9,8,7,1,6);
const Num2: array [0..10] of byte = (4,9,9,2,7,3,9,8,7,1,7);
const Num3: array [0..15] of byte = (1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8);
const Num4: array [0..15] of byte = (1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,0);
 
{Simplifies cases where we have to sum a two digit number}
 
const DigitSum: array [0..18] of byte = (0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9);
 
function ValidateCreditCard(CardNum: array of byte): boolean;
{Validate a Credit Card number}
var I,J,Len,Sum,Sum1,Sum2: integer;
var Rev: array of byte;
begin
Sum1:=0; Sum2:=0;
Len:=High(CardNum);
for I:=Len downto 0 do
if ((I-Len) and 1)=0 then Sum1:=Sum1 + CardNum[I]
else Sum2:=Sum2 + DigitSum[CardNum[I]*2];
Sum:=Sum1+Sum2;
Result:=(Sum mod 10)=0;
end;
 
 
function CardNumberToStr(CardNum: array of byte): string;
{Convert card number to a string}
var I: integer;
begin
Result:='';
for I:=0 to High(CardNum) do
Result:=Result+IntToStr(CardNum[I]);
end;
 
 
procedure TestDisplayNumber(Memo: TMemo; Num: array of byte);
{Test a credit card number and display results}
var S: string;
begin
S:=CardNumberToStr(Num);
if ValidateCreditCard(Num) then S:=S+': Valid'
else S:=S+': Not Valid';
Memo.Lines.Add(S);
end;
 
 
procedure TestCreditCardNums(Memo: TMemo);
{Test all credit card numbers}
begin
TestDisplayNumber(Memo,Num1);
TestDisplayNumber(Memo,Num2);
TestDisplayNumber(Memo,Num3);
TestDisplayNumber(Memo,Num4);
end;
 
 
</syntaxhighlight>
{{out}}
<pre>
49927398716: Valid
49927398717: Not Valid
1234567812345678: Not Valid
1234567812345670: Valid
 
</pre>
 
 
=={{header|Draco}}==
<syntaxhighlight lang="draco">proc nonrec luhn(*char num) bool:
[10] byte map = (0, 2, 4, 6, 8, 1, 3, 5, 7, 9);
byte total, digit;
*char start;
bool even;
start := num;
total := 0;
even := true;
while num* /= '\e' do num := num + 1 od;
while
num := num - 1;
num >= start
do
digit := num* - '0';
even := not even;
if even then digit := map[digit] fi;
total := total + digit
od;
total % 10 = 0
corp
 
proc nonrec test(*char num) void:
writeln(num, ": ", if luhn(num) then "pass" else "fail" fi)
corp
 
proc nonrec main() void:
test("49927398716");
test("49927398717");
test("1234567812345678");
test("1234567812345670")
corp</syntaxhighlight>
{{out}}
<pre>49927398716: pass
49927398717: fail
1234567812345678: fail
1234567812345670: pass</pre>
 
=={{header|EasyLang}}==
<syntaxhighlight>
func luhn cc$ .
for i = len cc$ downto 1
odd = 1 - odd
dig = number substr cc$ i 1
if odd = 0
dig = 2 * dig
if dig >= 10
dig -= 9
.
.
sum += dig
.
return if sum mod 10 = 0
.
cc$[] = [ "49927398716" "49927398717" "1234567812345678" "1234567812345670" ]
for cc$ in cc$[]
write cc$ & " "
if luhn cc$ = 1
print "is valid"
else
print "is not valid"
.
.
</syntaxhighlight>
{{out}}
<pre>
49927398716 is valid
49927398717 is not valid
1234567812345678 is not valid
1234567812345670 is valid
</pre>
 
=={{header|EchoLisp}}==
<langsyntaxhighlight lang="lisp">
;; value for 'even' numbers
(define (even-val n) (if (> n 4) (+ n n -9) (+ n n)))
Line 2,254 ⟶ 2,926:
(valid "1234567812345678") → #f
(valid "49927398717") → #f
</syntaxhighlight>
</lang>
 
=={{header|Elixir}}==
 
<langsyntaxhighlight lang="elixir">defmodule Luhn do
def valid?(cc) when is_binary(cc), do: String.to_integer(cc) |> valid?
def valid?(cc) when is_integer(cc) do
Line 2,270 ⟶ 2,942:
 
numbers = ~w(49927398716 49927398717 1234567812345678 1234567812345670)
for n <- numbers, do: IO.puts "#{n}: #{Luhn.valid?(n)}"</langsyntaxhighlight>
 
{{out}}
Line 2,281 ⟶ 2,953:
 
=={{header|Emacs Lisp}}==
{{libheader|seq.el}}
<lang lisp>
 
(require 'seq)
<syntaxhighlight lang="lisp">(require 'seq)
 
(defun luhn (str)
"Check if an input string STR is a valid credit card number using lhunthe Luhn algorithm."
(if (string-match-p "[^0-9]" str)
(error "String contains invalid character")
(let ((digit-list (reverse (mapcar #'(lambda (x) (- x 48))
(progn
(let ((digit-list (reverse (mapcar #'(lambda (x) (- x 48))
(string-to-list str)))))
(zerop
(mod (apply #'+ (seq-map-indexed
(lambda (elt idx)
(if (oddpnot (zerop (% idx 2)))
(if (> (* 2 elt) 9)
(- (* 2 elt) 9)
Line 2,299 ⟶ 2,972:
elt))
digit-list))
10))))))
 
(mapcar #'luhn '("49927398716" "49927398717" "1234567812345678" "1234567812345670"))</syntaxhighlight>
 
 
(mapcar #'luhn '("49927398716" "49927398717" "1234567812345678" "1234567812345670"))
</lang>
 
{{out}}
 
<pre> (t nil nil t) </pre>
(t nil nil t)
 
=={{header|Erlang}}==
<syntaxhighlight lang="erlang">
<lang Erlang>
-module(luhn_test).
 
Line 2,333 ⟶ 3,004:
Numbers = ["49927398716", "49927398717", "1234567812345678", "1234567812345670"],
[io:fwrite("~s: ~p~n", [X, credit_card(X)]) || X <- Numbers].
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,346 ⟶ 3,017:
=={{header|Euphoria}}==
{{trans|C}}
<langsyntaxhighlight lang="euphoria">function luhn(sequence cc)
integer isOdd, oddSum, evenSum, digit
isOdd = 1
Line 2,372 ⟶ 3,043:
for i = 1 to length(cc_numbers) do
printf(1,"%s = %d\n", {cc_numbers[i], luhn(cc_numbers[i])})
end for</langsyntaxhighlight>
 
{{out}}
Line 2,379 ⟶ 3,050:
1234567812345678 = 0
1234567812345670 = 1</pre>
 
=={{header|Excel}}==
===LAMBDA===
 
Binding the name '''luhnChecked''' to the following lambda expression in the Name Manager of the Excel WorkBook:
 
(See [https://www.microsoft.com/en-us/research/blog/lambda-the-ultimatae-excel-worksheet-function/ LAMBDA: The ultimate Excel worksheet function])
 
{{Works with|Office 365 betas 2021}}
<syntaxhighlight lang="lisp">luhnChecked
=LAMBDA(s,
LET(
ns, REVERSECOLS(VALUE(CHARSROW(s))),
ixs, SEQUENCE(1, COLUMNS(ns), 1, 1),
 
0 = MOD(SUM(
FILTER(ns, 0 <> MOD(ixs, 2))
) + (
LAMBDA(n,
DIGITSUM(
CONCAT(TEXT(2 * n, "0"))
)
)(
FILTER(ns, 0 = MOD(ixs, 2))
)
),
10
)
)
)</syntaxhighlight>
 
and also assuming the following generic bindings in the Name Manager for the WorkBook:
 
<syntaxhighlight lang="lisp">CHARSROW
=LAMBDA(s,
MID(s,
SEQUENCE(1, LEN(s), 1, 1),
1
)
)
 
 
DIGITSUM
=LAMBDA(s,
SUM(VALUE(
MID(s,
SEQUENCE(LEN(s), 1, 1, 1),
1
)
))
)
 
 
REVERSECOLS
=LAMBDA(xs,
LET(
n, COLUMNS(xs),
 
SORTBY(
xs,
SEQUENCE(1, n, n, -1)
)
)
)</syntaxhighlight>
 
{{Out}}
{| class="wikitable"
|-
|||style="text-align:right; font-family:serif; font-style:italic; font-size:120%;"|fx
! colspan="2" style="text-align:left; vertical-align: bottom; font-family:Arial, Helvetica, sans-serif !important;"|=luhnChecked(A2)
|- style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff;"
|
| A
| B
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 1
| style="font-weight:bold" | Digit strings
| style="font-weight:bold" | Luhn result
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 2
| style="text-align:right" | 49927398716
| style="background-color:#cbcefb" | TRUE
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 3
| style="text-align:right" | 49927398717
| FALSE
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 4
| style="text-align:right" | 1234567812345678
| FALSE
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 5
| style="text-align:right" | 1234567812345670
| TRUE
|}
 
=={{header|F Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">let luhn (s:string) =
let rec g r c = function
| 0 -> r
Line 2,387 ⟶ 3,153:
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</langsyntaxhighlight>
 
=={{header|Factor}}==
{{works with|Factor|0.98}}
<langsyntaxhighlight lang="factor">USING: kernel math math.parser math.order math.ranges sequences ;
IN: luhn
 
Line 2,409 ⟶ 3,175:
: luhn? ( n -- ? )
luhn-digit 0 = ;
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,424 ⟶ 3,190:
 
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">: luhn ( addr len -- ? )
0 >r over + ( R: sum )
begin 1- 2dup <=
Line 2,441 ⟶ 3,207:
s" 49927398717" luhn . \ 0
s" 1234567812345678" luhn . \ 0
s" 1234567812345670" luhn . \ -1</langsyntaxhighlight>
 
=={{header|Fortran}}==
<langsyntaxhighlight lang="fortran">program luhn
implicit none
integer :: nargs
Line 2,480 ⟶ 3,246:
! 49927398717 is not valid
! 1234567812345678 is not valid
! 1234567812345670 is valid</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight FreeBASIClang="freebasic">' version 05-07-2015
' compile with: fbc -s console
 
Line 2,540 ⟶ 3,306:
Print : Print "hit any key to end program"
Sleep
End</langsyntaxhighlight>
{{out}}
<pre>Task test number 49927398716 should be TRUE, report back as TRUE
Line 2,549 ⟶ 3,315:
1234567812345678 = FALSE
1234567812345670 = TRUE</pre>
 
=={{header|Free Pascal}}==
''see also: [[#Pascal|Pascal]]''
<syntaxhighlight lang="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.</syntaxhighlight>
 
{{out}}
<pre> 49927398716: TRUE
49927398717: FALSE
1234567812345678: FALSE
1234567812345670: TRUE</pre>
 
=={{header|FunL}}==
<langsyntaxhighlight lang="funl">def luhn_checksum( card_number ) =
def digits_of( n ) = [int(d) | d <- n.toString()]
Line 2,562 ⟶ 3,362:
 
for n <- [49927398716, 49927398717, 1234567812345678, 1234567812345670]
println( n + ' is ' + (if is_luhn_valid(n) then 'valid' else 'invalid') )</langsyntaxhighlight>
 
{{out}}
Line 2,571 ⟶ 3,371:
1234567812345678 is invalid
1234567812345670 is valid
</pre>
 
 
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"
 
local fn LuhnCheck( cardStr as CFStringRef ) as BOOL
NSInteger i, j, count, s1 = 0, s2 = 0
BOOL result = NO
// Build array of individual numbers in credit card string
NSUInteger strLength = len(cardStr)
CFMUtableArrayRef mutArr = fn MutableArrayWithCapacity(strLength)
for i = 0 to strLength - 1
CFStringRef tempStr = fn StringWithFormat( @"%C", fn StringCharacterAtIndex( cardStr, i ) )
MutableArrayInsertObjectAtIndex( mutArr, tempStr, i )
next
// Reverse the number array
CFArrayRef reversedArray = fn EnumeratorAllObjects( fn ArrayReverseObjectEnumerator( mutArr ) )
// Get number of array elements
count = len(reversedArray)
// Handle odd numbers
for i = 0 to count - 1 step 2
s1 = s1 + fn StringIntegerValue( reversedArray[i] )
next
// Hnadle even numbers
for i = 1 to count - 1 step 2
j = fn StringIntegerValue( reversedArray[i] )
j = j * 2
if j > 9 then j = j mod 10 + 1
s2 = s2 + j
next
 
if (s1 + s2) mod 10 = 0 then result = YES else result = NO
end fn = result
 
NSLogClear
if fn LuhnCheck( @"49927398716" ) then NSLog (@"%@ is valid.", @"49927398716" ) else NSLog (@"%@ is not valid.", @"49927398716" )
if fn LuhnCheck( @"49927398717" ) then NSLog (@"%@ is valid.", @"49927398717" ) else NSLog (@"%@ is not valid.", @"49927398717" )
if fn LuhnCheck( @"1234567812345678" ) then NSLog (@"%@ is valid.", @"1234567812345678" ) else NSLog (@"%@ is not valid.", @"1234567812345678" )
if fn LuhnCheck( @"1234567812345670" ) then NSLog (@"%@ is valid.", @"1234567812345670" ) else NSLog (@"%@ is not valid.", @"1234567812345670" )
 
HandleEvents
</syntaxhighlight>
{{output}}
<pre>
49927398716 is valid.
49927398717 is not valid.
1234567812345678 is not valid.
1234567812345670 is valid.
</pre>
 
=={{header|Gambas}}==
'''[https://gambas-playground.proko.eu/?gist=966f04aa2a1e9af43ba9553f5cb9160d Click this link to run this code]'''
<langsyntaxhighlight lang="gambas">Public Sub Main()
Dim sTrial As String[] = ["49927398716", "49927398717", "1234567812345678", "1234567812345670"]
Dim sRev As String
Line 2,610 ⟶ 3,466:
Next
 
End</langsyntaxhighlight>
Output:
<pre>
Line 2,620 ⟶ 3,476:
 
=={{header|GAP}}==
<langsyntaxhighlight lang="gap">IsLuhn := function(n)
local c, d, i, j, r;
d := "0123456789";
Line 2,642 ⟶ 3,498:
# Will also work on strings, and will skip non-digits
IsLuhn("4-992-739-871-6");
# true</langsyntaxhighlight>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 2,679 ⟶ 3,535:
fmt.Println(s, luhn(s))
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,689 ⟶ 3,545:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def checkLuhn(number) {
int total
(number as String).reverse().eachWithIndex { ch, index ->
Line 2,696 ⟶ 3,552:
}
total % 10 == 0
}</langsyntaxhighlight>
Testing the function:
<langsyntaxhighlight lang="groovy">def verifyLuhn(number, expected) {
println "Checking: $number (${checkLuhn(number)})"
assert expected == checkLuhn(number)
Line 2,705 ⟶ 3,561:
[49927398716: true, 49927398717: false, 1234567812345678: false, 1234567812345670: true].each { number, expected ->
verifyLuhn number, expected
}</langsyntaxhighlight>
{{out}}
<pre>Checking: 49927398716 (true)
Line 2,713 ⟶ 3,569:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Data.Char (digitToInt)
luhn = (0 ==) . (`mod` 10) . sum . map (uncurry (+) . (`divMod` 10)) .
zipWith (*) (cycle [1,2]) . map digitToInt . reverse</langsyntaxhighlight>
 
{{out}}
<langsyntaxhighlight lang="haskell">map luhn ["49927398716", "49927398717", "1234567812345678", "1234567812345670"]
[True,False,False,True]</langsyntaxhighlight>
 
Or, aiming for a legible relationship with the stages shown in the task description:
<langsyntaxhighlight lang="haskell">import Data.Char (digitToInt)
import Data.List (transpose)
import Data.List.Split (chunksOf)
Line 2,744 ⟶ 3,600:
"1234567812345678",
"1234567812345670"
]</langsyntaxhighlight>
{{Out}}
<pre>("49927398716",True)
Line 2,752 ⟶ 3,608:
 
=={{header|HicEst}}==
<langsyntaxhighlight HicEstlang="hicest">CHARACTER numbers="49927398716 49927398717 1234567812345678 1234567812345670 "
 
DO nr = 1, 4
Line 2,767 ⟶ 3,623:
valid = (0 == MOD(sum_odds + sum_even, 10))
WRITE() number, " is ", "invalid"(1 + 2*valid:)
ENDDO</langsyntaxhighlight>
<pre>49927398716 is valid
49927398717 is invalid
Line 2,775 ⟶ 3,631:
=={{header|Icon}} and {{header|Unicon}}==
We use map to pre-compute the sum of doubled digits.
<langsyntaxhighlight lang="icon">procedure main(aL)
every write(i := !aL ," - ", ((\isluhn10(i),"valid")|"invalid") \ 1)
end
Line 2,789 ⟶ 3,645:
 
return (sum % 10 = 0,i)
end</langsyntaxhighlight>
 
{{out}}
Line 2,800 ⟶ 3,656:
1234567812345670 - valid
</pre>
 
=={{header|IS-BASIC}}==
<lang IS-BASIC>100 PROGRAM "CredCard.bas"
110 DO
120 PRINT :PRINT "Credit card number:":INPUT PROMPT ">":CCN$
130 IF CCN$="" THEN EXIT DO
140 IF LUHN(TRIM$(CCN$)) THEN
150 PRINT "Card number is valid."
160 ELSE
170 SET #102:INK 3:PRINT "Card number is invalid.":SET #102:INK 1
180 END IF
190 LOOP
200 DEF LUHN(CCN$)
210 LET L=LEN(CCN$):LET S=0
220 FOR I=1 TO L
230 LET N=VAL(CCN$(L-I+1))
240 IF I BAND 1 THEN
250 LET S=S+N
260 ELSE
270 LET N=N*2:LET S=S+MOD(N,10)+INT(N/10)
280 END IF
290 NEXT
300 LET LUHN=MOD(S,10)=0
310 END DEF
320 DEF TRIM$(S$)
330 LET T$=""
340 FOR I=1 TO LEN(S$)
350 IF S$(I)>CHR$(47) AND S$(I)<CHR$(58) THEN LET T$=T$&S$(I)
360 NEXT
370 LET TRIM$=T$
380 END DEF</lang>
 
Output:
<pre>Credit card number:
>49927398716
Card number is valid.
 
Credit card number:
>49927398717
Card number is invalid.
 
Credit card number:
>1234 5678 1234 5678
Card number is invalid.
 
Credit card number:
>1234 5678 1234 5670
Card number is valid.</pre>
 
=={{header|J}}==
Line 2,855 ⟶ 3,663:
Also, we do not need the intermediate sums.
 
<langsyntaxhighlight Jlang="j">luhn=: 0 = 10 (| +/@,) 10 #.inv 1 2 *&|: _2 "."0\ |.</langsyntaxhighlight>
 
Example use:
<langsyntaxhighlight Jlang="j"> luhn&> '49927398716';'49927398717';'1234567812345678';'1234567812345670'
1 0 0 1</langsyntaxhighlight>
 
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.
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">public class Luhn {
public static void main(String[] args) {
System.out.println(luhnTest("49927398716"));
Line 2,888 ⟶ 3,696:
return (s1 + s2) % 10 == 0;
}
}</langsyntaxhighlight>
{{out}}
<pre>true
Line 2,894 ⟶ 3,702:
false
true</pre>
 
=={{header|Java Long type version}}==
<syntaxhighlight lang="java">public class Luhn {
public static void main(String[] args) {
System.out.println(luhnTest(49927398716L));
System.out.println(luhnTest(499273987163L));
System.out.println(luhnTest(1234567L));
System.out.println(luhnTest(0L));
}
 
public static boolean luhnTest(Long digits) {
int s1 = 0, s2 = 0;
//Use an alternator for separate odd/even processing
boolean alternator = true;
 
//Confine digit numbers to 8 - 19 per ISO
if (digits < 1e7 || digits >= 1e19) return false;
 
for ( int i = 0; digits > 0; ++i) {
Long oneDigit = digits % 10;
 
if (alternator) {
s1 += oneDigit.intValue();
} else {
oneDigit *= 2;
s2 += oneDigit > 9 ? oneDigit.intValue() - 9: oneDigit.intValue();
}
digits /= 10;
alternator = !alternator;
}
return (s1 + s2) % 10 == 0 ? true : false;
}
}</syntaxhighlight>
{{out}}
<pre>true
false
false
false</pre>
 
=={{header|JavaScript}}==
Using prototype.
<langsyntaxhighlight lang="javascript">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))});</langsyntaxhighlight>
 
Without any library.
<langsyntaxhighlight lang="javascript">var LuhnCheck = (function()
{
var luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
Line 2,923 ⟶ 3,769:
return (counter%10 == 0);
}
})();</langsyntaxhighlight>
 
Highly compressed version.
<langsyntaxhighlight lang="javascript">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;
Line 2,937 ⟶ 3,783:
// returns false
luhn10('4111111111111112')
</syntaxhighlight>
</lang>
 
Naive implementation
<syntaxhighlight lang="javascript">const lunhCheck = (str) => {
const sumDigit = (c) => (c < 10) ? c :
sumDigit( Math.trunc(c / 10) + (c % 10));
return str.split('').reverse()
.map(Number)
.map((c, i) => i % 2 !== 0 ? sumDigit(c * 2) : c)
.reduce((acc,v) => acc + v) % 10 === 0;
};
 
lunhCheck('49927398716'); // returns true
lunhCheck('49927398717'); // returns false
lunhCheck('1234567812345678'); // returns false
lunhCheck('1234567812345670'); // returns true
</syntaxhighlight>
 
=={{header|jq}}==
{{works with|jq|1.4 or later}}
<lang jq>def luhn:
'''Works with gojq, the Go implementation of jq'''
 
For the specific task defined here, both jq (version 1.4 or later)
and gojq should suffice, but for very large integers (greater than
2^53), either gojq or a version of the C implementation of jq with
support for very large external integers would be required.
 
<syntaxhighlight lang="jq">def luhn:
def odds: . as $in | reduce range(0; length) as $i
([]; if ($i % 2) == 0 then . + [$in[$i]] else . end);
Line 2,951 ⟶ 3,822:
| ($reverse | odds | digits | add) as $s1
| ($reverse | evens | digits | map(. * 2 | sumdigits) | add) as $s2
| 0 == ($s1 + $s2) % 10 ;</langsyntaxhighlight>
'''Example'''
<langsyntaxhighlight lang="jq"> ( 49927398716,
49927398717,
1234567812345678,
1234567812345670
) | "\(.) => \(luhn)";</langsyntaxhighlight>
{{Out}}
$ jq -r -M -n -f luhn.jq
Line 2,968 ⟶ 3,839:
The test function itself is only a single line of code:
 
<langsyntaxhighlight Julialang="julia">luhntest(x::Integer) = (sum(digits(x)[1:2:end]) + sum(map(x -> sum(digits(x)), 2 * digits(x)[2:2:end]))) % 10 == 0</langsyntaxhighlight>
 
More readable version:
 
<langsyntaxhighlight lang="julia">function luhntest(x::Integer)
d = reverse(digits(x))
s = sum(d[1:2:end])
Line 2,981 ⟶ 3,852:
for card in [49927398716, 49927398717, 1234567812345678, 1234567812345670]
println(luhntest(card) ? "PASS " : "FAIL ", card)
end</langsyntaxhighlight>
 
{{out}}
Line 2,991 ⟶ 3,862:
 
=={{header|K}}==
<langsyntaxhighlight lang="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}</langsyntaxhighlight>
 
{{trans|J}}
 
<langsyntaxhighlight lang="k">luhn2: {~(+/,//10_vs'1 2*+-1 2#((#n)!2){x,0}/n:0$'|$x)</langsyntaxhighlight>
 
'''Example:'''
 
<langsyntaxhighlight lang="k"> luhn'49927398716 49927398717 1234567812345678 1234567812345670
1 0 0 1
luhn2'49927398716 49927398717 1234567812345678 1234567812345670
1 0 0 1</langsyntaxhighlight>
 
{{Works with|K|3}}
<langsyntaxhighlight lang="k">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?
}</langsyntaxhighlight>
'''Example:'''
 
<langsyntaxhighlight lang="k"> test:("49927398716";"49927398717";"1234567812345678";"1234567812345670")
luhn'test
1 0 0 1</langsyntaxhighlight>
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.0
 
fun checkLuhn(number: String): Boolean {
Line 3,039 ⟶ 3,910:
for (number in numbers)
println("${number.padEnd(16)} is ${if(checkLuhn(number)) "valid" else "invalid"}")
}</langsyntaxhighlight>
 
{{out}}
Line 3,051 ⟶ 3,922:
=={{header|langur}}==
{{trans|Go}}
<syntaxhighlight lang="langur">val .luhntest = fn(.s) {
{{works with|langur|0.8.10}}
<lang langur>val .luhntest = f(.s) {
val .t = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
val .numbers = s2n .s
Line 3,062 ⟶ 3,932:
}
 
val .tests = h{
"49927398716": true,
"49927398717": false,
Line 3,073 ⟶ 3,943:
write .key, ": ", .pass
writeln if(.pass == .tests[.key]: ""; " (LUHN TEST FAILED)")
}</langsyntaxhighlight>
 
{{out}}
Line 3,083 ⟶ 3,953:
=={{header|Lasso}}==
Part of the Lasso's implementation of "valid_creditcard".
<langsyntaxhighlight lang="lasso">#!/usr/bin/lasso9
 
define luhn_check(number) => {
Line 3,106 ⟶ 3,976:
stdoutnl(luhn_check(49927398717)) // false
stdoutnl(luhn_check(1234567812345678)) // false
stdoutnl(luhn_check(1234567812345670)) // true</langsyntaxhighlight>
 
=={{header|Liberty BASIC}}==
<langsyntaxhighlight lang="lb">' [RC] Luhn test
 
card$(1)="49927398716"
Line 3,139 ⟶ 4,009:
print card$(test),"False"
end if
next</langsyntaxhighlight>
 
=={{header|LiveCode}}==
<langsyntaxhighlight LiveCodelang="livecode">function LuhnTest cc
local s1,evens, s2
repeat with n = 1 to len(cc)
Line 3,166 ⟶ 4,036:
1234567812345678 false
1234567812345670 true
</syntaxhighlight>
</lang>
 
=={{header|Logo}}==
<langsyntaxhighlight lang="logo">to small? :list
output or [empty? :list] [empty? bf :list]
end
Line 3,195 ⟶ 4,065:
show luhn "49927398717 ; false
show luhn "1234-5678-1234-5678 ; false
show luhn "1234-5678-1234-5670 ; true</langsyntaxhighlight>
 
=={{header|Lua}}==
<langsyntaxhighlight Lualang="lua">function luhn(n)
n=string.reverse(n)
print(n)
Line 3,228 ⟶ 4,098:
print(luhn'49927398717')
print(luhn'1234567812345678')
print(luhn'1234567812345670')</langsyntaxhighlight>
 
=={{header|M2000 Interpreter}}==
{{trans|FreeBASIC}}
<syntaxhighlight lang="m2000 interpreter">Module Checkit {
<lang M2000 Intertrpeter>
Module Checkit {
Function luhntest(cardnr$) {
Line 3,271 ⟶ 4,140:
end while
}
Checkit</syntaxhighlight>
</lang>
{{out}}
<pre>49927398716 = True
Line 3,279 ⟶ 4,147:
1234567812345670 = True</pre>
 
=={{header|MathematicaMACRO-11}}==
<syntaxhighlight lang="macro11"> .TITLE LUHN
<lang Mathematica>LuhnQ[nb_] := (Mod[Total[(2*ToExpression[#[[2;;All;;2]]]) /. {z_?(Function[v, v>9]) -> z-9}]
.MCALL .GTLIN,.PRINT,.EXIT
LUHN:: .GTLIN #5$
MOV #5$,R0
TSTB (R0)
BEQ 2$
JSR PC,TEST
BNE 1$
.PRINT #3$
BR LUHN
1$: .PRINT #4$
BR LUHN
2$: .EXIT
3$: .ASCIZ /PASS/
4$: .ASCIZ /FAIL/
5$: .BLKB 200
.EVEN
TEST: MOV R0,R1
CLR R2
1$: TSTB (R0)+
BNE 1$
DEC R0
2$: MOVB -(R0),R3
SUB #60,R3
ADD R3,R2
CMP R0,R1
BLOS 3$
MOVB -(R0),R3
SUB #60,R3
MOVB 4$(R3),R3
ADD R3,R2
CMP R0,R1
BHI 2$
3$: SUB #12,R2
BHI 3$
RTS PC
4$: .BYTE ^D0,^D2,^D4,^D6,^D8
.BYTE ^D1,^D3,^D5,^D7,^D9
.END LUHN</syntaxhighlight>
{{out}}
<pre>.LUHN 49927398716
PASS
 
.LUHN 49927398717
FAIL
 
.LUHN 1234567812345678
FAIL
 
.LUHN 1234567812345670
PASS</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="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}</langsyntaxhighlight>
===Alternate Code===
Eliminates conversion of numbers to strings and back
<langsyntaxhighlight Mathematicalang="mathematica">LuhnQ[n_Integer] :=
Block[{digits = Reverse@IntegerDigits@n},
Mod[Total[{digits[[;; ;; 2]],
IntegerDigits[2 #] & /@ digits[[2 ;; ;; 2]]}, -1], 10] == 0]
 
LuhnQ /@ {49927398716, 49927398717, 1234567812345678, 1234567812345670}</langsyntaxhighlight>
{{out}}<pre>{True,False,False,True}</pre>
 
=={{header|MATLAB}}==
The solution is basically the same as for [[#Octave|Octave]].
<langsyntaxhighlight MATLABlang="matlab">function passed = luhn(num)
if nargin == 0 % evaluate test cases
testnum = [49927398716 49927398717 1234567812345678 1234567812345670];
Line 3,309 ⟶ 4,231:
m = [2:2:8,1:2:9]; % rule 3: maps 1:9 to [2 4 6 8 1 3 5 7 9]
passed = ~mod(sum(d(end:-2:1)) + sum(m(d(end-1:-2:1))), 10);
end</langsyntaxhighlight>
{{out}}
<pre>49927398716: 1
Line 3,318 ⟶ 4,240:
=={{header|min}}==
{{works with|min|0.19.3}}
<langsyntaxhighlight lang="min">((dup 10 <) 'quote (((10 mod) (10 div)) cleave) 'cons linrec) :digits
((0 0) dip (pop 'succ dip over even?) partition ((pop pop) dip) dip) :evens/odds
((2 * digits sum) map sum) :evens-sum
Line 3,324 ⟶ 4,246:
 
(49927398716 49927398717 1234567812345678 1234567812345670)
(dup print! " " print! luhn? puts!) foreach</langsyntaxhighlight>
{{out}}
<pre>
Line 3,334 ⟶ 4,256:
 
=={{header|MiniScript}}==
<langsyntaxhighlight MiniScriptlang="miniscript">isValid = function(s)
sum = 0
odd = true
Line 3,353 ⟶ 4,275:
test "49927398717"
test "1234567812345678"
test "1234567812345670"</langsyntaxhighlight>
 
{{out}}
Line 3,362 ⟶ 4,284:
 
=={{header|MUMPS}}==
<langsyntaxhighlight lang="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)</langsyntaxhighlight>
<pre>USER>W !,$S($$LUHN^ROSETTA("49927398716")=0:"INVALID",1:"VALID")
Line 3,383 ⟶ 4,305:
=={{header|Nanoquery}}==
{{trans|Java}}
<langsyntaxhighlight Nanoquerylang="nanoquery">def reverse_str(string)
to_return = ""
 
Line 3,414 ⟶ 4,336:
println luhnTest("49927398717")
println luhnTest("1234567812345678")
println luhnTest("1234567812345670")</langsyntaxhighlight>
{{out}}
<pre>true
Line 3,422 ⟶ 4,344:
 
=={{header|NetRexx}}==
{{trans|REXX}}<langsyntaxhighlight lang="netrexx">
class LuhnTest
 
Line 3,449 ⟶ 4,371:
end
return s//10\==0
</syntaxhighlight>
</lang>
 
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">proc luhn(cc: string): bool =
const m = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
var sum = 0
Line 3,463 ⟶ 4,385:
for cc in ["49927398716", "49927398717", "1234567812345678", "1234567812345670"]:
echo cc, ' ', luhn(cc)</langsyntaxhighlight>
 
{{out}}
Line 3,472 ⟶ 4,394:
 
=={{header|Objeck}}==
<langsyntaxhighlight lang="objeck">bundle Default {
class Luhn {
function : IsValid(cc : String) ~ Bool {
Line 3,500 ⟶ 4,422:
}
}
}</langsyntaxhighlight>
 
=={{header|Objective-C}}==
<langsyntaxhighlight lang="objc">- (NSArray *) toCharArray {
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[self length]];
Line 3,540 ⟶ 4,462:
BOOL test1 = [self luhnCheck:@"49927398717"]; //Result = NO
BOOL test2 = [self luhnCheck:@"1234567812345678"]; //Result = NO
BOOL test3 = [self luhnCheck:@"1234567812345670"]; //Result = YES</langsyntaxhighlight>
 
=={{header|OCaml}}==
<langsyntaxhighlight lang="ocaml">let luhn s =
let rec g r c = function
| 0 -> r
Line 3,551 ⟶ 4,473:
in
(g 0 1 (String.length s)) mod 10 = 0
;;</langsyntaxhighlight>
 
{{out}}
<langsyntaxhighlight lang="ocaml"># List.map luhn [ "49927398716"; "49927398717"; "1234567812345678"; "1234567812345670" ];;
- : bool list = [true; false; false; true]</langsyntaxhighlight>
 
=={{header|Octave}}==
<langsyntaxhighlight Octavelang="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; </langsyntaxhighlight>
 
{{out}}
<langsyntaxhighlight lang="octave"> isluhn('49927398716')
ans = 1
isluhn('49927398717')
Line 3,574 ⟶ 4,496:
isluhn('1234567812345670')
ans = 1
</syntaxhighlight>
</lang>
 
=={{header|Oforth}}==
 
<langsyntaxhighlight Oforthlang="oforth">: luhnTest(n)
| s i |
n asString reverse ->s
Line 3,585 ⟶ 4,507:
i isEven ifTrue: [ 2 * dup 10 >= ifTrue: [ 9 - ] ] +
]
10 mod ==0 ; </langsyntaxhighlight>
 
{{out}}
Line 3,594 ⟶ 4,516:
 
=={{header|OpenEdge/Progress}}==
<langsyntaxhighlight lang="progress">FUNCTION fnLuhnAlgorithm RETURNS LOGICAL
(INPUT pcNumber AS CHARACTER):
/*------------------------------------------------------------------------------
Line 3,642 ⟶ 4,564:
RETURN FALSE.
 
END FUNCTION. /* fnLuhnAlgorithm */</langsyntaxhighlight>
 
{{out}}
Line 3,654 ⟶ 4,576:
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 <code>8nat</code>).
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.
<langsyntaxhighlight lang="c">#include <order/interpreter.h>
 
#define ORDER_PP_DEF_8luhn ORDER_PP_FN( \
Line 3,688 ⟶ 4,610:
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)))
))</langsyntaxhighlight>
{{out}}
<syntaxhighlight lang="text">(8true,8false,8false,8true)</langsyntaxhighlight>
 
=={{header|Oz}}==
<langsyntaxhighlight lang="oz">declare
fun {Luhn N}
{Sum {List.mapInd {Reverse {Digits N}}
Line 3,715 ⟶ 4,637:
{Map
[49927398716 49927398717 1234567812345678 1234567812345670]
Luhn}}</langsyntaxhighlight>
 
=={{header|Pascal}}==
''see also: [[#Free Pascal|Free Pascal]]''
<lang Pascal>program luhn;
{{works with|Extended Pascal}}
This implementation skips the ''reversal'' step and simply reads the input backwards.
<syntaxhighlight lang="pascal">program luhnTestOfCreditCardNumbers(input, output);
 
type
function lunh(arg: string): boolean;
{
var
`string(…)` is an Extended Pascal, ISO 10206, extension.
i, sum: integer;
`string(64)` discriminates the “schema” data type `string`
temp: byte;
to contain at most 64 `char` values.
begin
}
sum := 0;
creditCardNumber = string(64);
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;
 
{
\brief determines whether a string contains digits only
\param sample the string to inspect
\return `false` iff `sample` contains non-digit characters
}
{ Extended Pascal: `protected` means the function cannot modify `sample` }
function containsDigitsOnly(protected sample: creditCardNumber): Boolean;
var
{ EP: the `… value []` initializes this variable as an empty set }
characters: set of char value [];
{ `sample.capacity` refers to `64` in this code. }
i: 1..sample.capacity;
begin
for i := 1 to length(sample) do
writeln(' 49927398716: ', lunh('49927398716'));
begin
writeln(' 49927398717: ', lunh('49927398717'));
{ Union of sets indicated by `+`. }
writeln('1234567812345678: ', lunh('1234567812345678'));
characters := characters + [sample[i]]
writeln('1234567812345670: ', lunh('1234567812345670'));
end.</lang>;
{
In a Pascal `function` definition,
there must be one assignment to the (implicit) variable
bearing the same name as of the function.
This will be the return value.
}
{ NB: This will return `true` even if `length(sample)` is zero. }
containsDigitsOnly := card(characters - ['0'..'9']) = 0
{ `card` is an Extended Pascal extension. }
end;
 
{
\brief determines whether a string complies with ISO/IEC 7812-1 Luhn test
\param sample the potentially correct credit card number
\return `true` if verification succeeds
}
function luhnCheck(protected sample: creditCardNumber): Boolean;
{
This _nested_ function is only accessible _within_ `luhnCheck`.
Outsourcing this code allows us to write a neat expression below.
}
function check: Boolean;
var
{ Using `integer` sub-ranges ensures only these values are assigned. }
sum: 0..maxInt value 0;
i: 0..sample.capacity-1;
begin
for i := 0 to length(sample) - 1 do
begin
{ `1 + ord(odd(i))` produces an alternating scale factor `* 1`/`* 2`. }
sum := sum + (1 + ord(odd(i))) *
{ Obtain digit value for `integer` calculation. }
(ord(sample[length(sample) - i]) - ord('0')) -
{ Reverse operation if digit sum > 9, i.e. we added “too much”. }
ord(odd(i) and (sample[length(sample) - i] >= '5')) * 9
end;
check := sum mod 10 = 0
end;
begin
{
The Extended Pascal Boolean operator `and_then` (and `or_else`)
allows for “short-circuit evaluation”.
Otherwise, in Pascal `and` and `or` mandate complete evaluation.
}
luhnCheck := (length(sample) > 0) and_then containsDigitsOnly(sample)
and_then check
end;
 
{ === MAIN ============================================================= }
var
s: creditCardNumber;
begin
{ `EOF` is short for `EOF(input)`. }
while not EOF do
begin
readLn(s); { equivalent to `readLn(input, s)` }
writeLn(luhnCheck(s)) { = `writeLn(output, …)` }
end
end.</syntaxhighlight>
{{in}}
<pre>49927398716
49927398717
1234567812345678
1234567812345670</pre>
 
{{out}}
<pre>True
<pre> 49927398716: TRUE
False
49927398717: FALSE
False
1234567812345678: FALSE
1234567812345670: TRUETrue</pre>
The shown output was generated by a program compiled with the GPC, the [[GNU Pascal]] Compiler.
A different compiler may emit a different rendition of <tt>true</tt> and <tt>false</tt>, for example in all-caps.
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">sub luhn_test
{
my @rev = reverse split //,$_[0];
Line 3,767 ⟶ 4,765:
print luhn_test('49927398717');
print luhn_test('1234567812345678');
print luhn_test('1234567812345670');</langsyntaxhighlight>
 
Or using map( ) and a precomputed array:
 
<langsyntaxhighlight Perllang="perl">sub luhn {
my (@n,$i,$sum) = split //, reverse $_[0];
my @a = map {int(2*$_ / 10) + (2*$_ % 10)} (0..9);
Line 3,780 ⟶ 4,778:
# Test and display
map {print luhn($_), ": $_\n"}
qw(49927398716 49927398717 1234567812345678 1234567812345670);</langsyntaxhighlight>
 
{{out}}
Line 3,789 ⟶ 4,787:
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function Luhn(string st)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
integer s=0, d
<span style="color: #008080;">function</span> <span style="color: #000000;">Luhn</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">st</span><span style="color: #0000FF;">)</span>
for i=1 to length(st) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span>
d = st[i]-'0'
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">st</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
s += iff(mod(i,2)?d,d*2-(d>4)*9)
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">st</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]-</span><span style="color: #008000;">'0'</span>
end for
<span style="color: #000000;">s</span> <span style="color: #0000FF;">+=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;">-(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">></span><span style="color: #000000;">4</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
return remainder(s,10)=0
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure test(string s)
printf(1,"%20s : %s\n",{s,iff(Luhn(reverse(s))?"OK":"FAIL")})
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
end procedure
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%20s : %t\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Luhn</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)})</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
test("49927398716")
test("49927398717")
<span style="color: #7060A8;">papply</span><span style="color: #0000FF;">({</span><span style="color: #008000;">"49927398716"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"49927398717"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1234567812345678"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1234567812345670"</span><span style="color: #0000FF;">},</span><span style="color: #000000;">test</span><span style="color: #0000FF;">)</span>
test("1234567812345678")
<!--</syntaxhighlight>-->
test("1234567812345670")</lang>
{{out}}
<pre>
49927398716 : OKtrue
49927398717 : FAILfalse
1234567812345678 : FAILfalse
1234567812345670 : OKtrue
</pre>
 
=={{header|PHP}}==
{{trans|C}}
<langsyntaxhighlight lang="php">$numbers = "49927398716 49927398717 1234567812345678 1234567812345670";
foreach (split(' ', $numbers) as $n)
echo "$n is ", luhnTest($n) ? 'valid' : 'not valid', '</br>';
Line 3,831 ⟶ 4,829:
}
return $sum % 10 == 0;
}</langsyntaxhighlight>
{{out}}
<pre>49927398716 is valid
Line 3,839 ⟶ 4,837:
 
And a more concise example using PHP core methods:
<langsyntaxhighlight lang="php">function luhn_test($num) {
$str = '';
foreach( array_reverse( str_split( $num ) ) as $i => $c ) $str .= ($i % 2 ? $c * 2 : $c );
Line 3,846 ⟶ 4,844:
 
foreach (array('49927398716','49927398717','1234567812345678','1234567812345670') as $n)
echo "$n is ", luhn_test($n) ? 'valid' : 'not valid', "</br>\n";</langsyntaxhighlight>
{{out}}
<pre>49927398716 is valid
Line 3,853 ⟶ 4,851:
1234567812345670 is valid
</pre>
 
=={{header|Picat}}==
<syntaxhighlight lang="picat">go =>
Nums = ["49927398716","49927398717","1234567812345678","1234567812345670"],
foreach (N in Nums)
println([N, isluhn10(N)])
end,
nl.
 
%
% isluhn10(num) returns 1 is valid, else 0
%
% Assumption: input num is a string.
%
isluhn10(Num) = V =>
X = [I : I in Num.reverse()] ++ [""],
Digits = "0246813579",
M = new_map([(I.to_string()=Digits[I+1]) : I in 0..9]),
V1 = sum([X[I].to_integer() + M.get2(X[I+1].to_string(),0) : I in 1..2..Num.length]),
V := cond(V1 mod 10 == 0, 1, 0).
 
% A variant of Map.get with conversions
get2(M, Key, Default)=V =>
if M.has_key(Key) then V= M.get(Key).to_integer() else V=Default end.</syntaxhighlight>
 
{{out}}
<pre>[49927398716,1]
[49927398717,0]
[1234567812345678,0]
[1234567812345670,1]</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de luhn (Num) # 'Num' may be a number or a string
(=0
(%
Line 3,866 ⟶ 4,894:
(flip (chop Num))
'(T NIL .) )
10 ) ) )</langsyntaxhighlight>
{{out}}
<pre>: (mapcar luhn (49927398716 49927398717 1234567812345678 1234567812345670))
Line 3,872 ⟶ 4,900:
 
=={{header|PL/I}}==
<langsyntaxhighlight lang="pli">test: procedure options (main);
 
declare (cardnumber, rcn) character (20) varying;
Line 3,895 ⟶ 4,923:
put skip edit (cardnumber, ' does not pass the Luhn test' )(a);
put skip list (s1 + s2);
end test;</langsyntaxhighlight>
 
{{out}}
Line 3,910 ⟶ 4,938:
Comment: it isn't necessary to reverse the string
in order to perform the test.
 
=={{header|PL/M}}==
<syntaxhighlight lang="pli">100H:
BDOS: PROCEDURE(F,A); DECLARE F BYTE, A ADDRESS; GO TO 5; END BDOS;
EXIT: PROCEDURE; GO TO 0; END EXIT;
PRINT: PROCEDURE(S); DECLARE S ADDRESS; CALL BDOS(9,S); END PRINT;
 
LUHN: PROCEDURE(NUM) BYTE;
DECLARE MAP DATA (0, 2, 4, 6, 8, 1, 3, 5, 7, 9);
DECLARE (START, NUM, MASK, TOTAL) ADDRESS;
DECLARE (CHR BASED NUM, DGT) BYTE;
START = NUM;
DO WHILE CHR <> '$'; NUM = NUM + 1; END;
MASK = NUM := NUM - 1;
TOTAL = 0;
DO WHILE NUM >= START;
DGT = CHR - '0';
IF NUM XOR MASK THEN DGT = MAP(DGT);
TOTAL = TOTAL + DGT;
NUM = NUM - 1;
END;
RETURN TOTAL MOD 10 = 0;
END LUHN;
 
DECLARE TEST (4) ADDRESS, I BYTE;
TEST(0) = .'49927398716$';
TEST(1) = .'49927398717$';
TEST(2) = .'1234567812345678$';
TEST(3) = .'1234567812345670$';
 
DO I=0 TO LAST(TEST);
CALL PRINT(TEST(I));
CALL PRINT(.': $');
IF LUHN(TEST(I))
THEN CALL PRINT(.'PASS$');
ELSE CALL PRINT(.'FAIL$');
CALL PRINT(.(13,10,'$'));
END;
CALL EXIT;
EOF</syntaxhighlight>
{{out}}
<pre>49927398716: PASS
49927398717: FAIL
1234567812345678: FAIL
1234567812345670: PASS</pre>
 
=={{header|PL/SQL}}==
<langsyntaxhighlight PLSQLlang="plsql">FUNCTION algoLuhn ( p_numeroVerif VARCHAR2 )
RETURN NUMBER
IS
Line 3,944 ⟶ 5,018:
RETURN 1;
END algoLuhn;</langsyntaxhighlight>
 
=={{header|Plain English}}==
<langsyntaxhighlight lang="plainenglish">To run:
Start up.
Test whether "49927398716" will pass the luhn test.
Line 3,990 ⟶ 5,064:
 
To convert a byte to a number:
If the byte is any digit, put the byte minus 48 into the number.</langsyntaxhighlight>
{{out}}
<pre>
Line 4,001 ⟶ 5,075:
=={{header|PowerBASIC}}==
{{trans|Visual Basic}}
<langsyntaxhighlight lang="powerbasic">#COMPILE EXE
#DIM ALL
#COMPILER PBCC 6
Line 4,030 ⟶ 5,104:
' this test is expected to pass:
CON.PRINT IIF$(LuhnCheckPassed("1234567812345670"), "passed", "failed")
END FUNCTION</langsyntaxhighlight>
{{out}}
<pre>passed
Line 4,038 ⟶ 5,112:
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Test-LuhnNumber
{
Line 4,099 ⟶ 5,173:
($sumOdds + $sumEvens).ToString()[-1] -eq "0"
}
</syntaxhighlight>
</lang>
<syntaxhighlight lang="powershell">
<lang PowerShell>
Test-LuhnNumber 49927398716
</syntaxhighlight>
</lang>
{{Out}}
<pre>
True
</pre>
<syntaxhighlight lang="powershell">
<lang PowerShell>
49927398716, 49927398717, 1234567812345678, 1234567812345670 | ForEach-Object {
"{0,-17}: {1}" -f $_,"$(if(Test-LuhnNumber $_) {'Is valid.'} else {'Is not valid.'})"
}
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 4,121 ⟶ 5,195:
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">DataSection
Sample:
Data.s "49927398716"
Line 4,175 ⟶ 5,249:
Input()
CloseConsole()
EndIf</langsyntaxhighlight>
{{out}}
<pre>49927398716 is valid
Line 4,185 ⟶ 5,259:
===Functional===
The [http://docs.python.org/py3k/library/functions.html#divmod divmod] in the function below conveniently splits a number into its two digits ready for summing:
<langsyntaxhighlight lang="python">>>> 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))</langsyntaxhighlight>
 
{{out}}
Line 4,200 ⟶ 5,274:
Or, using itertools ''cycle'' with map and reduce:
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''Luhn test of credit card numbers'''
 
from operator import add, mul
Line 4,236 ⟶ 5,310:
 
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>[True, False, False, True]</pre>
Line 4,244 ⟶ 5,318:
and cycle lambdas rather than integers.
 
<langsyntaxhighlight lang="python">'''Luhn test of credit card numbers'''
 
from itertools import cycle
Line 4,282 ⟶ 5,356:
if __name__ == '__main__':
main()
</syntaxhighlight>
</lang>
{{Out}}
<pre>('49927398716', True)
Line 4,291 ⟶ 5,365:
===Procedural===
Without usingsum() and divmod() functions:
<langsyntaxhighlight lang="python">>>> def vérifLuhn(ch):
sum = 0
chParity = len(ch) % 2
Line 4,306 ⟶ 5,380:
for n in (49927398716, 49927398717, 1234567812345678, 1234567812345670):
print (str(n)+" =>", vérifLuhn(str(n)))
</syntaxhighlight>
</lang>
 
=={{header|Q}}==
<langsyntaxhighlight lang="q">sd:{s:0; while[x<>0; s+:x mod 10; x:floor x%10]; s} / Sum digits of x
luhn:{
r:reverse string x; / Reversed credit card number
Line 4,315 ⟶ 5,389:
e:("I"$) each r[1+2*til floor (count r) % 2]; / Even-indexed numbers
0=(sum o,sd each e*2) mod 10 / Return 1b if checksum ends in 0; 0b otherwise
}</langsyntaxhighlight>
 
{{out}}
Line 4,323 ⟶ 5,397:
=={{header|Quackery}}==
 
<langsyntaxhighlight Quackerylang="quackery"> [ 1 & ] is odd ( n --> b )
 
[ [] swap
Line 4,365 ⟶ 5,439:
else
[ say " invalid" ]
cr ]</langsyntaxhighlight>
 
{{out}}
Line 4,376 ⟶ 5,450:
=={{header|R}}==
 
<langsyntaxhighlight lang="rsplus">
is.luhn <- function(cc){
numbers <- as.numeric(rev(unlist(strsplit(cc,""))))
Line 4,384 ⟶ 5,458:
sapply(c("49927398716","49927398717","1234567812345678","1234567812345670"),is.luhn)
 
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,393 ⟶ 5,467:
=={{header|Racket}}==
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 4,406 ⟶ 5,480:
(map luhn-test '(49927398716 49927398717 1234567812345678 1234567812345670))
;; -> '(#t #f #f #t)
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 4,420 ⟶ 5,494:
If you rename it or change its behavior, make sure to update that task as well.
-->
<syntaxhighlight lang="raku" perl6line>sub luhn-test ($number --> Bool) {
my @digits = $number.comb.reverse;
my $sum = @digits[0,2...*].sum
Line 4,442 ⟶ 5,516:
is luhn-test(+$cc), $expected-result,
"$cc {$expected-result ?? 'passes' !! 'does not pass'} the Luhn test.";
}</langsyntaxhighlight>
 
{{out}}
Line 4,451 ⟶ 5,525:
ok 4 - 1234567812345670 passes the Luhn test.</pre>
 
=={{header|Refal}}==
<syntaxhighlight lang="refal">$ENTRY Go {
= <Test '49927398716'>
<Test '49927398717'>
<Test '1234567812345678'>
<Test '1234567812345670'>;
};
 
Test {
e.Digits = <Prout e.Digits ': ' <Luhn e.Digits>>;
};
 
Luhn {
(s.Sum) e.Digits s.Even s.Odd,
<Mul 2 <Numb s.Even>>: s.Even2,
<Divmod s.Even2 10>: (s.EvenD1) s.EvenD2,
<+ s.EvenD1 s.EvenD2>: s.EvenV,
<+ <Numb s.Odd> s.EvenV>: s.Step
= <Luhn (<+ s.Sum s.Step>) e.Digits>;
(s.Sum) s.Odd = <Luhn (<+ s.Sum <Numb s.Odd>>)>;
(s.Sum), <Divmod s.Sum 10>: (s.Rest) s.Last,
s.Last: {
0 = Valid;
s.X = Invalid;
};
e.Digits = <Luhn (0) e.Digits>;
};</syntaxhighlight>
{{out}}
<pre>49927398716: Valid
49927398717: Invalid
1234567812345678: Invalid
1234567812345670: Valid</pre>
=={{header|REXX}}==
===version 1===
<langsyntaxhighlight REXXlang="rexx">/*REXX program validates credit card numbers using the Luhn algorithm. */
#.=; #.1= 49927398716 /*the 1st sample credit card number. */
#.2= 49927398717 /* " 2nd " " " " */
Line 4,468 ⟶ 5,574:
$= $ + substr(y, j, 1) + left(_, 1) + substr(_, 2, 1, 0) /* ◄────────┐*/
end /*j*/ /*sum odd and even decimal digits ►────┘*/
return word('passed flunked',1+($//10==0)) /*$ ending in zero? Then the # passed.*/</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the (internal) default inputs:}}
<pre>
Line 4,478 ⟶ 5,584:
 
===Version 2===
<langsyntaxhighlight REXXlang="rexx">/* Rexx ***************************************************
* 09.04.2013 Walter Pachl
* Implements the task's description in a rather concise way
Line 4,513 ⟶ 5,619:
sum=sum+c /* add into test sum */
End
Return right(sum,1)=0 /* ok if last digit is 0 */ </langsyntaxhighlight>
{{out}}
<pre>
Line 4,523 ⟶ 5,629:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">decimals(0)
 
test = ["49927398716", "49927398717", "1234567812345678", "1234567812345670"]
Line 4,581 ⟶ 5,687:
next
return sumarr
</syntaxhighlight>
</lang>
Output:
<pre>
Line 4,588 ⟶ 5,694:
1234567812345678 -> Invalid
1234567812345670 -> Valid
</pre>
 
=={{header|RPL}}==
Card numbers shall be entered as strings to avoid any rounding error when testing long ones.
{{works with|RPL|HP48-C}}
{| class="wikitable"
! RPL code
! Comment
|-
|
« 0 → card even
« 0
card SIZE 1 '''FOR''' j
card j DUP SUB OBJ→
'''IF''' even '''THEN'''
DUP + 10 MOD LASTARG / IP + '''END'''
+ 1 'even' STO-
-1 '''STEP'''
10 MOD NOT
» » '<span style="color:blue">LUHN?</span>' STO
|
<span style="color:blue">LUHN?</span> ''( "card_number" -- boolean ) ''
sum = 0
loop for j=n to 1
digit = card[j]
if even digit
multiply it by 2 and add digits
sum += digit ; reverse parity flag
return not(sum mod 10)
|}
{ "49927398716" "49927398717" "1234567812345678" "1234567812345670" } 1 « <span style="color:blue">LUHN?</span> » DOLIST
{{out}}
<pre>
1: { 1 0 0 1 }
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby"> def luhn_valid?(str)
str.scan(/\d/).reverse #using str.to_i.digits fails for cases with leading zeros
.each_slice(2)
Line 4,599 ⟶ 5,741:
 
["49927398716", "49927398717", "1234567812345678", "1234567812345670"].map{ |i| luhn_valid?(i) }
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,605 ⟶ 5,747:
 
Simpler Alternative
<langsyntaxhighlight lang="ruby">def luhn_valid?(n) # Card values can be numbers or strings
d2sum = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
sum, num = 0, n.to_i
Line 4,613 ⟶ 5,755:
 
cards = [49927398716, "49927398717", 1234567812345678, "1234567812345670"]
cards.each{ |i| puts "#{i}: #{luhn_valid?(i)}" }</langsyntaxhighlight>
 
{{out}}
Line 4,622 ⟶ 5,764:
 
=={{header|Run BASIC}}==
<langsyntaxhighlight lang="runbasic">card$(1) = "49927398716"
card$(2) = "49927398717"
card$(3) = "1234567812345678"
Line 4,638 ⟶ 5,780:
next i
if chkSum mod 10 = 0 then luhn$ = "True" else luhn$ = "False"
end function</langsyntaxhighlight>
{{out}}
<pre>49927398716 True
Line 4,646 ⟶ 5,788:
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">extern crate luhn_test_of_credit_card_numbers;
 
use luhn_test_of_credit_card_numbers::luhn_test;
Line 4,694 ⟶ 5,836:
assert_eq!(validate_isin("FR0000988040"), true);
}
}</langsyntaxhighlight>
{{out}}
<pre>49927398716: true
Line 4,705 ⟶ 5,847:
 
===Functional style===
<langsyntaxhighlight lang="scala">object Luhn {
private def parse(s: String): Seq[Int] = s.map{c =>
assert(c.isDigit)
Line 4,730 ⟶ 5,872:
assert(Luhn.validate(n) == expected)
}
}</langsyntaxhighlight>
{{out}}
<pre>49927398716 true
Line 4,738 ⟶ 5,880:
 
===Imperative style===
<langsyntaxhighlight lang="scala"> def luhnTest1(number: String): Boolean = {
var (odd, sum) = (true, 0)
 
Line 4,747 ⟶ 5,889:
}
sum % 10 == 0
}</langsyntaxhighlight>
 
=={{header|Scheme}}==
<langsyntaxhighlight lang="scheme">(define luhn
(lambda (n)
(let loop ((number n)
Line 4,763 ⟶ 5,905:
(remainder number 10)
(let ((part (* 2 (remainder number 10))))
(+ (remainder part 10) (quotient part 10))))))))))</langsyntaxhighlight>
{{out}}
<pre>
Line 4,771 ⟶ 5,913:
 
=={{header|sed}}==
<langsyntaxhighlight lang="sed"># Split number into double evens and odds
s/.*/&: /
: split
Line 4,798 ⟶ 5,940:
/0:/!a\
Fail
d</langsyntaxhighlight>
 
{{out}}
Line 4,815 ⟶ 5,957:
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const func boolean: luhnTest (in string: cardNumber) is func
Line 4,846 ⟶ 5,988:
writeln(cardNumber <& ": " <& luhnTest(cardNumber));
end for;
end func;</langsyntaxhighlight>
 
{{out}}
Line 4,857 ⟶ 5,999:
 
=={{header|SenseTalk}}==
<langsyntaxhighlight lang="sensetalk">function LuhnCheck ccNum
put length of ccNum into numDigits
put the last character of ccNum into total
Line 4,872 ⟶ 6,014:
end repeat
return total is divisible by 10
end LuhnCheck</langsyntaxhighlight>
 
<langsyntaxhighlight lang="sensetalk">repeat for each item of (49927398716, 49927398717, 1234567812345678, 1234567812345670)
put it && LuhnCheck(it)
end repeat</langsyntaxhighlight>
 
=={{header|SequenceL}}==
<syntaxhighlight lang="sequencel">
<lang sequenceL>
main(args(2)) :=
sum(luhnTest(asciiToInt(args[1]) - asciiToInt('0'))) mod 10 = 0;
Line 4,888 ⟶ 6,030:
x[i] when i mod 2 = size(x) mod 2 else
s2Mapping[x[i] + 1];
</syntaxhighlight>
</lang>
 
=={{header|Shen}}==
<langsyntaxhighlight lang="shen">
(define mapi
_ _ [] -> []
Line 4,912 ⟶ 6,054:
 
(map (function luhn?) ["49927398716" "49927398717" "1234567812345678" "1234567812345670"])
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,927 ⟶ 6,069:
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">func luhn (n) {
static a = {|j| (2*j // 10) + (2*j % 10) }.map(^10)
 
Line 4,939 ⟶ 6,081:
for n in [49927398716, 49927398717, 1234567812345678, 1234567812345670] {
say [n, luhn(n)]
}</langsyntaxhighlight>
 
{{out}}
Line 4,949 ⟶ 6,091:
=={{header|SNOBOL4}}==
Using a precomputed array.
<langsyntaxhighlight SNOBOL4lang="snobol4"> 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 displayok = array('0:1')
test = " outputok<0> = luhn(n) ': FAIL' n"
n ok<1> = '49927398716OK'; eval(test)
 
n = '49927398717'; eval(test)
* n =Test '1234567812345678';and eval(test)display
n = define('1234567812345670test(n)';) eval :(testtest_end)
test output = n ': ' ok<luhn(n)> :(return)
end</lang>
test_end
 
test('49927398716')
test('49927398717')
test('1234567812345678')
test('1234567812345670')
end
</syntaxhighlight>
 
{{out}}
<pre>149927398716: 49927398716OK
49927398717: FAIL
0: 49927398717
1234567812345678: FAIL
0: 1234567812345678
1234567812345670: OK</pre>
1: 1234567812345670</pre>
 
=={{header|SparForte}}==
As a structured script.
<syntaxhighlight lang="ada">#!/usr/local/bin/spar
pragma annotate( summary, "luhn test of credit card numbers" )
@( description, "The Luhn test is used by some credit card companies to " )
@( description, "distinguish valid credit card numbers from what could be a random selection of digits." )
@( see_also, "https://rosettacode.org/wiki/Luhn_test_of_credit_card_number" )
@( author, "Ken O. Burtch" );
pragma license( unrestricted );
 
pragma restriction( no_external_commands );
 
procedure luhn is
 
bad_digit : exception;
 
-- return true if the card number passes the luhn test
 
function is_luhn( card_number : string) return boolean is
card_num_len : constant natural := strings.length( card_number );
checksum: natural := 0;
ch : character;
begin
for i in reverse 1..card_num_len loop
ch := strings.element( card_number, i );
if strings.is_digit( ch ) then
declare
ord : constant natural := numerics.pos(ch);
begin
if ((card_num_len-1) and (i-1) ) /= 0 then
checksum := @ + ord;
else
checksum := @ + numerics.floor(ord / 5) + ((2*ord) mod 10);
end if;
end;
else
raise bad_digit;
end if;
end loop;
return checksum mod 10 = 0;
end is_luhn;
 
-- check a credit card and display the result
 
procedure check_card( card_number : string ) is
begin
put( card_number )
@( ": " )
@( is_luhn( card_number ) );
new_line;
end check_card;
 
begin
check_card("49927398716");
check_card("49927398717");
check_card("1234567812345678");
check_card("1234567812345670");
end luhn;</syntaxhighlight>
 
=={{header|SPARK}}==
Line 4,979 ⟶ 6,188:
 
A final test has been added which passes as valid unless there is an explicit test for all digits.
<langsyntaxhighlight lang="ada">with Spark_IO;
--# inherit Spark_IO;
--# main_program;
Line 5,038 ⟶ 6,247:
Do_Test("1234567812345670");
Do_Test("123456781234567D");
end Luhn;</langsyntaxhighlight>
{{out}}
<pre>49927398716 is valid.
Line 5,049 ⟶ 6,258:
{{works with|Db2 LUW}}
With SQL PL:
<langsyntaxhighlight lang="sql pl">
--#SET TERMINATOR @
 
Line 5,126 ⟶ 6,335:
END
@
</syntaxhighlight>
</lang>
Output:
<pre>
Line 5,175 ⟶ 6,384:
 
=={{header|Standard ML}}==
<langsyntaxhighlight lang="sml">local
fun revDigits 0 = []
| revDigits n = (n mod 10) :: revDigits (n div 10)
Line 5,196 ⟶ 6,405:
val res = [true, false, false, true] : bool list
[closing file "luhn.sml"]
*)</langsyntaxhighlight>
 
=={{header|Swift}}==
<langsyntaxhighlight lang="swift">func luhn(_ number: String) -> Bool {
return number.reversed().enumerated().map({
let digit = Int(String($0.element))!
Line 5,208 ⟶ 6,417:
 
luhn("49927398716") // true
luhn("49927398717") // false</langsyntaxhighlight>
 
=={{header|Tcl}}==
Based on an algorithmic encoding for the test on Wikipedia.
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
proc luhn digitString {
if {[regexp {[^0-9]} $digitString]} {error "not a number"}
Line 5,224 ⟶ 6,433:
}
return [expr {($sum % 10) == 0}]
}</langsyntaxhighlight>
Driver:
<langsyntaxhighlight lang="tcl">foreach testNumber {
49927398716
49927398717
Line 5,234 ⟶ 6,443:
puts [format "%s is %s" $testNumber \
[lindex {"NOT valid" "valid"} [luhn $testNumber]]]
}</langsyntaxhighlight>
{{out}}
<pre>
Line 5,244 ⟶ 6,453:
 
=={{header|Terraform}}==
<langsyntaxhighlight lang="hcl">variable number {
type = "string"
}
Line 5,262 ⟶ 6,471:
output "valid" {
value = local.check == 0
}</langsyntaxhighlight>
{{Out}}
<pre>$ terraform apply
Line 5,282 ⟶ 6,491:
 
=={{header|TI-83 BASIC}}==
<langsyntaxhighlight lang="ti83b">PROGRAM:LUHN
:Disp "ENTER NUMBER"
:Input Str1
Line 5,307 ⟶ 6,516:
:Disp "BAD CARD"
:End
</syntaxhighlight>
</lang>
 
=={{header|Transact-SQL}}==
 
<syntaxhighlight lang="transact-sql">
<lang Transact-SQL>
CREATE FUNCTION dbo._CreditCardNumCheck( @strCCNum VarChar(40) )
RETURNS VarChar(7)
Line 5,331 ⟶ 6,540:
RETURN CASE WHEN (SELECT SUM(S_Value) FROM @table) % 10 = 0 THEN 'Valid' ELSE 'Invalid' END
END
</syntaxhighlight>
</lang>
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">$$ MODE TUSCRIPT
MODE DATA
$$ SET cardnumbers=*
Line 5,374 ⟶ 6,583:
PRINT c,"false"
ENDIF
ENDLOOP</langsyntaxhighlight>
{{out}}
<pre>
Line 5,385 ⟶ 6,594:
=={{header|TXR}}==
 
<langsyntaxhighlight lang="txr">@(do (defun luhn (num)
(for ((i 1) (sum 0))
((not (zerop num)) (zerop (mod sum 10)))
Line 5,399 ⟶ 6,608:
@ccnumber -> @(if (luhn (int-str ccnumber 10)) "good" "bad")
@(end)
@(end)</langsyntaxhighlight>
 
<pre>$ txr luhn.txr luhn.txt
Line 5,410 ⟶ 6,619:
{{works with|bash}}
{{works with|ksh}}
<langsyntaxhighlight lang="bash">function luhn {
typeset n p s t=('0123456789' '0516273849')
while ((-n<${#1})); do
Line 5,425 ⟶ 6,634:
echo $c is valid
fi
done</langsyntaxhighlight>
 
Notes:
Line 5,439 ⟶ 6,648:
 
=={{header|Ursala}}==
<langsyntaxhighlight Ursalalang="ursala">#import std
#import nat
 
luhn = %nP; %np*hxiNCNCS; not remainder\10+ //sum:-0@DrlrHK32 ~&iK27K28TK25 iota10</langsyntaxhighlight>
 
Some notes on this solution:
Line 5,457 ⟶ 6,666:
* The output from the function is tested for divisibility by 10 with <code>remainder\10</code>, with the result negated so that zero values map to true and non-zero to false.
usage:
<langsyntaxhighlight lang="ursala">#cast %bL
 
test = luhn* <49927398716,49927398717,1234567812345678,1234567812345670></langsyntaxhighlight>
{{out}}
<pre>
Line 5,466 ⟶ 6,675:
 
=={{header|VBA}}==
<syntaxhighlight lang="vb">
<lang VB>
Option Explicit
 
Line 5,493 ⟶ 6,702:
Luhn = "invalid"
End If
End Function</langsyntaxhighlight>
{{out}}
<pre>Number 49927398716 is valid
Line 5,501 ⟶ 6,710:
 
=={{header|VBScript}}==
<langsyntaxhighlight VBScriptlang="vbscript">Function Luhn_Test(cc)
cc = RevString(cc)
s1 = 0
Line 5,533 ⟶ 6,742:
WScript.Echo "49927398717 is " & Luhn_Test("49927398717")
WScript.Echo "1234567812345678 is " & Luhn_Test("1234567812345678")
WScript.Echo "1234567812345670 is " & Luhn_Test("1234567812345670")</langsyntaxhighlight>
 
{{out}}
Line 5,543 ⟶ 6,752:
=={{header|Visual Basic}}==
{{works with|Visual Basic|VB6 Standard}}
<langsyntaxhighlight lang="vb">Public Function LuhnCheckPassed(ByVal dgts As String) As Boolean
Dim i As Long, s As Long, s1 As Long
dgts = VBA.StrReverse(dgts)
Line 5,557 ⟶ 6,766:
Next i
LuhnCheckPassed = Not CBool(s Mod 10)
End Function</langsyntaxhighlight>
 
Test:
<langsyntaxhighlight lang="vb">Sub Main()
Debug.Assert LuhnCheckPassed("49927398716")
Debug.Assert Not LuhnCheckPassed("49927398717")
Debug.Assert Not LuhnCheckPassed("1234567812345678")
Debug.Assert LuhnCheckPassed("1234567812345670")
End Sub</langsyntaxhighlight>
 
=={{header|Visual Basic .NET}}==
<syntaxhighlight lang="visual basic .net">
<lang Visual Basic .NET>
Imports System.Linq
Function ValidLuhn(value As String)
Line 5,579 ⟶ 6,788:
Console.WriteLine(ValidLuhn("1234567812345670"))
End Sub
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,586 ⟶ 6,795:
False
True
</pre>
 
=={{header|V (Vlang)}}==
{{trans|go}}
<syntaxhighlight lang="v (vlang)">const (
input = '49927398716
49927398717
1234567812345678
1234567812345670'
t = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
)
fn luhn(s string) bool {
odd := s.len & 1
mut sum := 0
for i, c in s.split('') {
if c < '0' || c > '9' {
return false
}
if i&1 == odd {
sum += t[c.int()-'0'.int()]
} else {
sum += c.int() - '0'.int()
}
}
return sum%10 == 0
}
fn main() {
for s in input.split("\n") {
println('$s ${luhn(s)}')
}
}</syntaxhighlight>
{{out}}
<pre>
49927398716 true
49927398717 false
1234567812345678 false
1234567812345670 true
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-fmt}}
{{libheader|Wren-traititerate}}
<langsyntaxhighlight ecmascriptlang="wren">import "./fmt" for Fmt
import "./traititerate" for Stepped
 
var luhn = Fn.new { |s|
Line 5,611 ⟶ 6,860:
for (test in tests) {
var ans = (luhn.call(test)) ? "pass" : "fail"
SystemFmt.print("%(Fmt.$-16s -> $s(-16", test)), -> %(ans)")
}</langsyntaxhighlight>
 
{{out}}
Line 5,623 ⟶ 6,872:
 
=={{header|Xojo}}==
<langsyntaxhighlight lang="xojo">Public Function Modulus10(digits As String) as String
//
// Confirm the digits are really, well, digits
Line 5,658 ⟶ 6,907:
return Modulus10( digits ) = checkDigit
End Function
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,668 ⟶ 6,917:
 
=={{header|XPL0}}==
<langsyntaxhighlight XPL0lang="xpl0">string 0; \use zero-terminated strings
 
func Valid(Str); \Return 'true' if digits in Str pass Luhn test
Line 5,699 ⟶ 6,948:
CrLf(0);
];
]</langsyntaxhighlight>
 
{{out}}
Line 5,710 ⟶ 6,959:
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn luhnTest(n){
0 == (n.split().reverse().reduce(fcn(s,n,clk){
s + if(clk.next()) n else 2*n%10 + n/5 },0,Walker.cycle(1,0)) %10)
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">T(49927398716,49927398717,1234567812345678,1234567812345670)
.apply(luhnTest).println();</langsyntaxhighlight>
{{out}}
<pre>
Line 5,722 ⟶ 6,971:
 
=={{header|ZX Spectrum Basic}}==
<langsyntaxhighlight ZXBasiclang="zxbasic">10 LET c$="49927398716": GO SUB 1000
20 LET c$="49927398717": GO SUB 1000
30 LET c$="1234567812345678": GO SUB 1000
Line 5,746 ⟶ 6,995:
1150 IF s$(LEN s$)="0" THEN PRINT c$;" VALID!": LET retval=1: RETURN
1160 PRINT c$;" INVALID!": LET retval=0: RETURN
</syntaxhighlight>
</lang>
{{out}}
<pre>
885

edits