Luhn test of credit card numbers: Difference between revisions
m
→{{header|langur}}
Langurmonkey (talk | contribs) |
|||
(48 intermediate revisions by 29 users not shown) | |||
Line 47:
{{trans|Python}}
<
V ch = String(n)
V sum = 0
Line 64:
1234567812345678,
1234567812345670)
print(luhn(n))</
{{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.
<
LUHNTEST CSECT
USING LUHNTEST,R13 base register
Line 199:
PG DC CL80' ' buffer
YREGS
END LUHNTEST</
{{out}}
<pre>
Line 209:
=={{header|8080 Assembly}}==
<
jmp demo
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Line 269:
jmp 5
pass: db 'Pass$'
fail: db 'Fail$'</
{{out}}
Line 284:
=={{header|8086 Assembly}}==
<
cpu 8086
org 100h
Line 351:
section .data
pass: db 'Pass$'
fail: db 'Fail$'</
{{out}}
Line 366:
=={{header|8th}}==
<syntaxhighlight lang="forth">
\ Adapted from the C version:
: remap \ n1 -- n2
Line 391:
"1234567812345670" test-luhn
bye</
{{out}}
Line 403:
=={{header|ABAP}}==
<
DATA: sum(1) TYPE n VALUE 0. " Sum of checksum.
Line 430:
ENDIF.
ENDMETHOD.</
=={{header|ACL2}}==
<
(defun digits (n)
Line 467:
(sum (double-and-sum-digits evens)))
10)
0)))</
{{out}}
Line 478:
> (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}}==
<
{
var isOdd:Boolean = true;
Line 499 ⟶ 577:
trace(isValid("49927398717"));
trace(isValid("1234567812345678"));
trace(isValid("1234567812345670"));</
=={{header|Ada}}==
{{trans|C}}
{{works with|GNAT}}
<
use Ada.Text_IO;
Line 533 ⟶ 611:
Put_Line (Boolean'Image (Luhn_Test ("1234567812345670")));
end Luhn;</
{{out}}
<pre>
Line 548 ⟶ 626:
{{works with|ELLA ALGOL 68|Any (with appropriate job cards)}}
<
ABS c - ABS "0";
Line 581 ⟶ 659:
print((cp, ": ", confirm(cp), new line))
OD
)</
{{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]]
<
% 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</
Use the above to test the LuhnTest procedure:
<
% 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.</
{{out}}
<pre>
Line 650 ⟶ 728:
=={{header|APL}}==
{{works with|Dyalog APL}}
<
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
}</
{{out}}
<pre>
Line 663 ⟶ 741:
{{works with|APL+Win}}
<
[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
∇</
{{out}}
<pre> LuhnTest¨ 49927398716 49927398717 1234567812345678 1234567812345670
Line 676 ⟶ 754:
=={{header|AppleScript}}==
===Functional===
<
on luhn(s)
-- True if the digit string represents
Line 839 ⟶ 917:
return lst
end tell
end zipWith</
{{Out}}
<pre>{true, false, false, true}</pre>
Line 845 ⟶ 923:
===Straightforward===
<
-- 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</
{{output}}
<
=={{header|ARM Assembly}}==
<syntaxhighlight lang="arm_assembly">.text
.global _start
_start:
Line 1,058 ⟶ 1,136:
.asciz "49927398717"
.asciz "1234567812345678"
.asciz "1234567812345670" </
=={{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}}==
<
; 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)
}</
=={{header|AutoIt}}==
<syntaxhighlight lang="autoit">
Global $avarray[4] = [49927398716, 49927398717, 1234567812345678, 1234567812345670]
For $i = 0 To 3
Line 1,106 ⟶ 1,222:
EndIf
EndFunc ;==>checkLuhn
</syntaxhighlight>
{{out}}
Line 1,115 ⟶ 1,231:
=={{header|AWK}}==
<
BEGIN {
A[1] = 49927398716;
Line 1,138 ⟶ 1,254:
}
return ((s%10)==0);
}</
{{out}}
<pre>isLuhn(1234567812345670): 1
Line 1,149 ⟶ 1,265:
=={{header|Bash}}==
<
function luhn_validate # <numeric-string>
Line 1,188 ⟶ 1,304:
print_result "49927398717"
print_result "1234567812345678"
print_result "1234567812345670"</
{{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.
<
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"
:digit_loop
) else (
set /a "twice=!input:~%cnt%,1!*2"
if !twice! geq 10 (
set /a "s2+=!twice:~0,1!+!twice:~1,1!"
) else (
set /a
)
)
if "!input:~%cnt%!"=="!input!" (
set /a "sum=(!s1!+!s2!)%%10"
if !sum! equ 0 (echo !input! is valid.) else (echo !input! is not valid.)
goto :EOF
)
goto digit_loop</syntaxhighlight>
{{Out}}
<pre>>luhn.bat
Line 1,242 ⟶ 1,604:
=={{header|BBC BASIC}}==
<
READ cardnumber$
IF FNluhn(cardnumber$) THEN
Line 1,266 ⟶ 1,628:
ENDIF
NEXT
= (S% MOD 10) = 0</
=={{header|bc}}==
<
define l(n) {
auto m, o, s, x
Line 1,294 ⟶ 1,656:
l(49927398717)
l(1234567812345678)
l(1234567812345670)</
{{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}}==
<
>&:19+`|v < >v 5 6 7 8
^ \ <>09p19p>09g+09p:|>2*:19+%19g+19p19+/19g+19p:|
Line 1,313 ⟶ 1,703:
>:#,_@
11
</syntaxhighlight>
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}}==
<
= sum odd even
. 0:?sum
Line 1,370 ⟶ 1,772:
& test$1234567812345678
& test$1234567812345670
& ;</
{{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>
{{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}}==
<
#include <stdio.h>
Line 1,459 ⟶ 1,916:
return 0;
}</
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.
<
public static class Luhn
{
Line 1,497 ⟶ 1,954:
}
}
</syntaxhighlight>
<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.
<
using System.Linq;
Line 1,550 ⟶ 2,007:
}
}
}</
<pre>
49927398716 is valid
Line 1,559 ⟶ 2,016:
A solution without using LINQ, works for all versions of .NET.
<
using System;
namespace Luhn_Test
Line 1,610 ⟶ 2,067:
}
}
</syntaxhighlight>
<pre>
1234567812345670 is Valid.
Line 1,619 ⟶ 2,076:
A solution optimized for readability:
<
using System;
using System.Linq;
Line 1,642 ⟶ 2,099:
}
}
</syntaxhighlight>
Extremely compact version uses Europa rtl library https://github.com/CodeAlkemist/Europa-rtl
<
using System;
using EuropaRTL.Utilities;
Line 1,676 ⟶ 2,133:
}
}
</syntaxhighlight>
<pre>
49927398716
Line 1,689 ⟶ 2,146:
=={{header|C++}}==
<
using namespace std;
Line 1,731 ⟶ 2,188:
}
return 0;
}</
===C++11===
<
#include <vector>
#include <algorithm>
Line 1,755 ⟶ 2,212:
return 0;
}
</syntaxhighlight>
It is also possible to achieve a compile-time version using metaprogramming.
<
#include <type_traits>
Line 1,853 ⟶ 2,310:
return 0;
}
</syntaxhighlight>
<pre>
true
Line 1,863 ⟶ 2,320:
=={{header|Caché ObjectScript}}==
<
{
Line 1,879 ⟶ 2,336:
}
}</
{{out|Examples}}
<pre>USER>For { Read ccn Quit:ccn="" Write ": "_##class(Utils.Check).Luhn(ccn), ! }
Line 1,890 ⟶ 2,347:
=={{header|Ceylon}}==
<
value numbers = "49927398716
49927398717
Line 1,916 ⟶ 2,373:
};
return (s1 + s2) % 10 == 0;
}</
=={{header|Clojure}}==
<
(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)))</
=={{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}}
<
PROGRAM-ID. LUHNTEST.
ENVIRONMENT DIVISION.
Line 2,018 ⟶ 2,509:
goback
.
END PROGRAM LUHN.</
{{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}}==
<
(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))))))</
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:
<
(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)))</
=={{header|Cowgol}}==
<
# Given a string containing the digits of a credit card number,
Line 2,110 ⟶ 2,634:
test("49927398717");
test("1234567812345678");
test("1234567812345670");</
{{out}}
Line 2,119 ⟶ 2,643:
=={{header|Crystal}}==
<
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)}" }</
{{out}}
<pre>49927398716: true
Line 2,137 ⟶ 2,661:
===Functional Version===
{{trans|Haskell}}
<
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]));
}</
===More Imperative Version===
{{trans|C}}
<
bool luhnTest(in string num) @safe pure nothrow @nogc {
Line 2,170 ⟶ 2,694:
"1234567812345670"];
assert(data.map!luhnTest.equal([true, false, false, true]));
}</
===Stronger Statically Typed Version===
This version uses more precise types.
{{trans|SPARK}}
<
struct Interval(T) {
Line 2,234 ⟶ 2,758:
"123456781234567D"])
writefln("%s is %svalid", n, luhnTest(n) ? "" : "not ");
}</
=={{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}}==
<
;; 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>
=={{header|Elixir}}==
<
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)}"</
{{out}}
Line 2,281 ⟶ 2,953:
=={{header|Emacs Lisp}}==
{{libheader|seq.el}}
<syntaxhighlight lang="lisp">(require 'seq)
(defun luhn (str)
"Check if
(if (string-match-p "[^0-9]" str)
(error "String contains invalid character")
(let ((digit-list (reverse (mapcar #'(lambda (x) (- x 48))
(string-to-list str)))))
(zerop
(mod (apply #'+ (seq-map-indexed
(lambda (elt idx)
(if (
(if (> (* 2 elt) 9)
(- (* 2 elt) 9)
Line 2,299 ⟶ 2,972:
elt))
digit-list))
10
(mapcar #'luhn '("49927398716" "49927398717" "1234567812345678" "1234567812345670"))</syntaxhighlight>
{{out}}
(t nil nil t)
=={{header|Erlang}}==
<syntaxhighlight 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>
{{out}}
Line 2,346 ⟶ 3,017:
=={{header|Euphoria}}==
{{trans|C}}
<
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</
{{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#}}==
<
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</
=={{header|Factor}}==
{{works with|Factor|0.98}}
<
IN: luhn
Line 2,409 ⟶ 3,175:
: luhn? ( n -- ? )
luhn-digit 0 = ;
</syntaxhighlight>
{{out}}
Line 2,424 ⟶ 3,190:
=={{header|Forth}}==
<
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</
=={{header|Fortran}}==
<
implicit none
integer :: nargs
Line 2,480 ⟶ 3,246:
! 49927398717 is not valid
! 1234567812345678 is not valid
! 1234567812345670 is valid</
=={{header|FreeBASIC}}==
<
' compile with: fbc -s console
Line 2,540 ⟶ 3,306:
Print : Print "hit any key to end program"
Sleep
End</
{{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}}==
<
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') )</
{{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]'''
<
Dim sTrial As String[] = ["49927398716", "49927398717", "1234567812345678", "1234567812345670"]
Dim sRev As String
Line 2,610 ⟶ 3,466:
Next
End</
Output:
<pre>
Line 2,620 ⟶ 3,476:
=={{header|GAP}}==
<
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</
=={{header|Go}}==
<
import (
Line 2,679 ⟶ 3,535:
fmt.Println(s, luhn(s))
}
}</
{{out}}
<pre>
Line 2,689 ⟶ 3,545:
=={{header|Groovy}}==
<
int total
(number as String).reverse().eachWithIndex { ch, index ->
Line 2,696 ⟶ 3,552:
}
total % 10 == 0
}</
Testing the function:
<
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
}</
{{out}}
<pre>Checking: 49927398716 (true)
Line 2,713 ⟶ 3,569:
=={{header|Haskell}}==
<
luhn = (0 ==) . (`mod` 10) . sum . map (uncurry (+) . (`divMod` 10)) .
zipWith (*) (cycle [1,2]) . map digitToInt . reverse</
{{out}}
<
[True,False,False,True]</
Or, aiming for a legible relationship with the stages shown in the task description:
<
import Data.List (transpose)
import Data.List.Split (chunksOf)
Line 2,744 ⟶ 3,600:
"1234567812345678",
"1234567812345670"
]</
{{Out}}
<pre>("49927398716",True)
Line 2,752 ⟶ 3,608:
=={{header|HicEst}}==
<
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</
<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.
<
every write(i := !aL ," - ", ((\isluhn10(i),"valid")|"invalid") \ 1)
end
Line 2,789 ⟶ 3,645:
return (sum % 10 = 0,i)
end</
{{out}}
Line 2,800 ⟶ 3,656:
1234567812345670 - valid
</pre>
=={{header|J}}==
Line 2,855 ⟶ 3,663:
Also, we do not need the intermediate sums.
<
Example use:
<
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.
=={{header|Java}}==
<
public static void main(String[] args) {
System.out.println(luhnTest("49927398716"));
Line 2,888 ⟶ 3,696:
return (s1 + s2) % 10 == 0;
}
}</
{{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.
<
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 luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
Line 2,923 ⟶ 3,769:
return (counter%10 == 0);
}
})();</
Highly compressed version.
<
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>
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}}
'''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 ;</
'''Example'''
<
49927398717,
1234567812345678,
1234567812345670
) | "\(.) => \(luhn)";</
{{Out}}
$ jq -r -M -n -f luhn.jq
Line 2,968 ⟶ 3,839:
The test function itself is only a single line of code:
<
More readable version:
<
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</
{{out}}
Line 2,991 ⟶ 3,862:
=={{header|K}}==
<
se: {+/{+/0$'$x}'2*x@1+2*!(#x)%2}
luhn: {n:|0$'$x; 0=((se n)+so n)!10}</
{{trans|J}}
<
'''Example:'''
<
1 0 0 1
luhn2'49927398716 49927398717 1234567812345678 1234567812345670
1 0 0 1</
{{Works with|K|3}}
<
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:'''
<
luhn'test
1 0 0 1</
=={{header|Kotlin}}==
<
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"}")
}</
{{out}}
Line 3,051 ⟶ 3,922:
=={{header|langur}}==
{{trans|Go}}
<syntaxhighlight lang="langur">val .luhntest = fn(.s) {
val .t = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
val .numbers = s2n .s
Line 3,062 ⟶ 3,932:
}
val .tests =
"49927398716": true,
"49927398717": false,
Line 3,073 ⟶ 3,943:
write .key, ": ", .pass
writeln if(.pass == .tests[.key]: ""; " (LUHN TEST FAILED)")
}</
{{out}}
Line 3,083 ⟶ 3,953:
=={{header|Lasso}}==
Part of the Lasso's implementation of "valid_creditcard".
<
define luhn_check(number) => {
Line 3,106 ⟶ 3,976:
stdoutnl(luhn_check(49927398717)) // false
stdoutnl(luhn_check(1234567812345678)) // false
stdoutnl(luhn_check(1234567812345670)) // true</
=={{header|Liberty BASIC}}==
<
card$(1)="49927398716"
Line 3,139 ⟶ 4,009:
print card$(test),"False"
end if
next</
=={{header|LiveCode}}==
<
local s1,evens, s2
repeat with n = 1 to len(cc)
Line 3,166 ⟶ 4,036:
1234567812345678 false
1234567812345670 true
</syntaxhighlight>
=={{header|Logo}}==
<
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</
=={{header|Lua}}==
<
n=string.reverse(n)
print(n)
Line 3,228 ⟶ 4,098:
print(luhn'49927398717')
print(luhn'1234567812345678')
print(luhn'1234567812345670')</
=={{header|M2000 Interpreter}}==
{{trans|FreeBASIC}}
<syntaxhighlight lang="m2000 interpreter">Module Checkit {
Function luhntest(cardnr$) {
Line 3,271 ⟶ 4,140:
end while
}
Checkit</syntaxhighlight>
{{out}}
<pre>49927398716 = True
Line 3,279 ⟶ 4,147:
1234567812345670 = True</pre>
=={{header|
<syntaxhighlight lang="macro11"> .TITLE LUHN
.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}</
===Alternate Code===
Eliminates conversion of numbers to strings and back
<
Block[{digits = Reverse@IntegerDigits@n},
Mod[Total[{digits[[;; ;; 2]],
IntegerDigits[2 #] & /@ digits[[2 ;; ;; 2]]}, -1], 10] == 0]
LuhnQ /@ {49927398716, 49927398717, 1234567812345678, 1234567812345670}</
{{out}}<pre>{True,False,False,True}</pre>
=={{header|MATLAB}}==
The solution is basically the same as for [[#Octave|Octave]].
<
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</
{{out}}
<pre>49927398716: 1
Line 3,318 ⟶ 4,240:
=={{header|min}}==
{{works with|min|0.19.3}}
<
((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</
{{out}}
<pre>
Line 3,334 ⟶ 4,256:
=={{header|MiniScript}}==
<
sum = 0
odd = true
Line 3,353 ⟶ 4,275:
test "49927398717"
test "1234567812345678"
test "1234567812345670"</
{{out}}
Line 3,362 ⟶ 4,284:
=={{header|MUMPS}}==
<
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)</
<pre>USER>W !,$S($$LUHN^ROSETTA("49927398716")=0:"INVALID",1:"VALID")
Line 3,383 ⟶ 4,305:
=={{header|Nanoquery}}==
{{trans|Java}}
<
to_return = ""
Line 3,414 ⟶ 4,336:
println luhnTest("49927398717")
println luhnTest("1234567812345678")
println luhnTest("1234567812345670")</
{{out}}
<pre>true
Line 3,422 ⟶ 4,344:
=={{header|NetRexx}}==
{{trans|REXX}}<
class LuhnTest
Line 3,449 ⟶ 4,371:
end
return s//10\==0
</syntaxhighlight>
=={{header|Nim}}==
<
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)</
{{out}}
Line 3,472 ⟶ 4,394:
=={{header|Objeck}}==
<
class Luhn {
function : IsValid(cc : String) ~ Bool {
Line 3,500 ⟶ 4,422:
}
}
}</
=={{header|Objective-C}}==
<
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</
=={{header|OCaml}}==
<
let rec g r c = function
| 0 -> r
Line 3,551 ⟶ 4,473:
in
(g 0 1 (String.length s)) mod 10 = 0
;;</
{{out}}
<
- : bool list = [true; false; false; true]</
=={{header|Octave}}==
<
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; </
{{out}}
<
ans = 1
isluhn('49927398717')
Line 3,574 ⟶ 4,496:
isluhn('1234567812345670')
ans = 1
</syntaxhighlight>
=={{header|Oforth}}==
<
| s i |
n asString reverse ->s
Line 3,585 ⟶ 4,507:
i isEven ifTrue: [ 2 * dup 10 >= ifTrue: [ 9 - ] ] +
]
10 mod ==0 ; </
{{out}}
Line 3,594 ⟶ 4,516:
=={{header|OpenEdge/Progress}}==
<
(INPUT pcNumber AS CHARACTER):
/*------------------------------------------------------------------------------
Line 3,642 ⟶ 4,564:
RETURN FALSE.
END FUNCTION. /* fnLuhnAlgorithm */</
{{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.
<
#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)))
))</
{{out}}
<syntaxhighlight lang="text">(8true,8false,8false,8true)</
=={{header|Oz}}==
<
fun {Luhn N}
{Sum {List.mapInd {Reverse {Digits N}}
Line 3,715 ⟶ 4,637:
{Map
[49927398716 49927398717 1234567812345678 1234567812345670]
Luhn}}</
=={{header|Pascal}}==
''see also: [[#Free Pascal|Free Pascal]]''
{{works with|Extended Pascal}}
This implementation skips the ''reversal'' step and simply reads the input backwards.
<syntaxhighlight lang="pascal">program luhnTestOfCreditCardNumbers(input, output);
type
{
`string(…)` is an Extended Pascal, ISO 10206, extension.
`string(64)` discriminates the “schema” data type `string`
to contain at most 64 `char` values.
}
creditCardNumber = string(64);
{
\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
begin
{ Union of sets indicated by `+`. }
characters := characters + [sample[i]]
end
{
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
False
False
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}}==
<
{
my @rev = reverse split //,$_[0];
Line 3,767 ⟶ 4,765:
print luhn_test('49927398717');
print luhn_test('1234567812345678');
print luhn_test('1234567812345670');</
Or using map( ) and a precomputed array:
<
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);</
{{out}}
Line 3,789 ⟶ 4,787:
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<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>
<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>
<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>
<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>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<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>
<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>
<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>
<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>
<!--</syntaxhighlight>-->
{{out}}
<pre>
49927398716 :
49927398717 :
1234567812345678 :
1234567812345670 :
</pre>
=={{header|PHP}}==
{{trans|C}}
<
foreach (split(' ', $numbers) as $n)
echo "$n is ", luhnTest($n) ? 'valid' : 'not valid', '</br>';
Line 3,831 ⟶ 4,829:
}
return $sum % 10 == 0;
}</
{{out}}
<pre>49927398716 is valid
Line 3,839 ⟶ 4,837:
And a more concise example using PHP core methods:
<
$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";</
{{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}}==
<
(=0
(%
Line 3,866 ⟶ 4,894:
(flip (chop Num))
'(T NIL .) )
10 ) ) )</
{{out}}
<pre>: (mapcar luhn (49927398716 49927398717 1234567812345678 1234567812345670))
Line 3,872 ⟶ 4,900:
=={{header|PL/I}}==
<
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;</
{{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}}==
<
RETURN NUMBER
IS
Line 3,944 ⟶ 5,018:
RETURN 1;
END algoLuhn;</
=={{header|Plain English}}==
<
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.</
{{out}}
<pre>
Line 4,001 ⟶ 5,075:
=={{header|PowerBASIC}}==
{{trans|Visual Basic}}
<
#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</
{{out}}
<pre>passed
Line 4,038 ⟶ 5,112:
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
function Test-LuhnNumber
{
Line 4,099 ⟶ 5,173:
($sumOdds + $sumEvens).ToString()[-1] -eq "0"
}
</syntaxhighlight>
<syntaxhighlight lang="powershell">
Test-LuhnNumber 49927398716
</syntaxhighlight>
{{Out}}
<pre>
True
</pre>
<syntaxhighlight lang="powershell">
49927398716, 49927398717, 1234567812345678, 1234567812345670 | ForEach-Object {
"{0,-17}: {1}" -f $_,"$(if(Test-LuhnNumber $_) {'Is valid.'} else {'Is not valid.'})"
}
</syntaxhighlight>
{{Out}}
<pre>
Line 4,121 ⟶ 5,195:
=={{header|PureBasic}}==
<
Sample:
Data.s "49927398716"
Line 4,175 ⟶ 5,249:
Input()
CloseConsole()
EndIf</
{{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:
<
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))</
{{out}}
Line 4,200 ⟶ 5,274:
Or, using itertools ''cycle'' with map and reduce:
{{Works with|Python|3.7}}
<
from operator import add, mul
Line 4,236 ⟶ 5,310:
if __name__ == '__main__':
main()</
{{Out}}
<pre>[True, False, False, True]</pre>
Line 4,244 ⟶ 5,318:
and cycle lambdas rather than integers.
<
from itertools import cycle
Line 4,282 ⟶ 5,356:
if __name__ == '__main__':
main()
</syntaxhighlight>
{{Out}}
<pre>('49927398716', True)
Line 4,291 ⟶ 5,365:
===Procedural===
Without usingsum() and divmod() functions:
<
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>
=={{header|Q}}==
<
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
}</
{{out}}
Line 4,323 ⟶ 5,397:
=={{header|Quackery}}==
<
[ [] swap
Line 4,365 ⟶ 5,439:
else
[ say " invalid" ]
cr ]</
{{out}}
Line 4,376 ⟶ 5,450:
=={{header|R}}==
<
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>
{{out}}
Line 4,393 ⟶ 5,467:
=={{header|Racket}}==
<syntaxhighlight lang="racket">
#lang racket
Line 4,406 ⟶ 5,480:
(map luhn-test '(49927398716 49927398717 1234567812345678 1234567812345670))
;; -> '(#t #f #f #t)
</syntaxhighlight>
=={{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"
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.";
}</
{{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===
<
#.=; #.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.*/</
{{out|output|text= when using the (internal) default inputs:}}
<pre>
Line 4,478 ⟶ 5,584:
===Version 2===
<
* 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 */ </
{{out}}
<pre>
Line 4,523 ⟶ 5,629:
=={{header|Ring}}==
<
test = ["49927398716", "49927398717", "1234567812345678", "1234567812345670"]
Line 4,581 ⟶ 5,687:
next
return sumarr
</syntaxhighlight>
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}}==
<
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>
{{out}}
Line 4,605 ⟶ 5,747:
Simpler Alternative
<
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)}" }</
{{out}}
Line 4,622 ⟶ 5,764:
=={{header|Run BASIC}}==
<
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</
{{out}}
<pre>49927398716 True
Line 4,646 ⟶ 5,788:
=={{header|Rust}}==
<
use luhn_test_of_credit_card_numbers::luhn_test;
Line 4,694 ⟶ 5,836:
assert_eq!(validate_isin("FR0000988040"), true);
}
}</
{{out}}
<pre>49927398716: true
Line 4,705 ⟶ 5,847:
===Functional style===
<
private def parse(s: String): Seq[Int] = s.map{c =>
assert(c.isDigit)
Line 4,730 ⟶ 5,872:
assert(Luhn.validate(n) == expected)
}
}</
{{out}}
<pre>49927398716 true
Line 4,738 ⟶ 5,880:
===Imperative style===
<
var (odd, sum) = (true, 0)
Line 4,747 ⟶ 5,889:
}
sum % 10 == 0
}</
=={{header|Scheme}}==
<
(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))))))))))</
{{out}}
<pre>
Line 4,771 ⟶ 5,913:
=={{header|sed}}==
<
s/.*/&: /
: split
Line 4,798 ⟶ 5,940:
/0:/!a\
Fail
d</
{{out}}
Line 4,815 ⟶ 5,957:
=={{header|Seed7}}==
<
const func boolean: luhnTest (in string: cardNumber) is func
Line 4,846 ⟶ 5,988:
writeln(cardNumber <& ": " <& luhnTest(cardNumber));
end for;
end func;</
{{out}}
Line 4,857 ⟶ 5,999:
=={{header|SenseTalk}}==
<
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</
<
put it && LuhnCheck(it)
end repeat</
=={{header|SequenceL}}==
<syntaxhighlight 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>
=={{header|Shen}}==
<
(define mapi
_ _ [] -> []
Line 4,912 ⟶ 6,054:
(map (function luhn?) ["49927398716" "49927398717" "1234567812345678" "1234567812345670"])
</syntaxhighlight>
{{out}}
Line 4,927 ⟶ 6,069:
=={{header|Sidef}}==
<
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)]
}</
{{out}}
Line 4,949 ⟶ 6,091:
=={{header|SNOBOL4}}==
Using a precomputed array.
<
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 output = n ': ' ok<luhn(n)> :(return)
test_end
test('49927398716')
test('49927398717')
test('1234567812345678')
test('1234567812345670')
end
</syntaxhighlight>
{{out}}
<pre>
49927398717: FAIL
1234567812345678: FAIL
1234567812345670: OK</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.
<
--# inherit Spark_IO;
--# main_program;
Line 5,038 ⟶ 6,247:
Do_Test("1234567812345670");
Do_Test("123456781234567D");
end Luhn;</
{{out}}
<pre>49927398716 is valid.
Line 5,049 ⟶ 6,258:
{{works with|Db2 LUW}}
With SQL PL:
<
--#SET TERMINATOR @
Line 5,126 ⟶ 6,335:
END
@
</syntaxhighlight>
Output:
<pre>
Line 5,175 ⟶ 6,384:
=={{header|Standard ML}}==
<
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"]
*)</
=={{header|Swift}}==
<
return number.reversed().enumerated().map({
let digit = Int(String($0.element))!
Line 5,208 ⟶ 6,417:
luhn("49927398716") // true
luhn("49927398717") // false</
=={{header|Tcl}}==
Based on an algorithmic encoding for the test on Wikipedia.
<
proc luhn digitString {
if {[regexp {[^0-9]} $digitString]} {error "not a number"}
Line 5,224 ⟶ 6,433:
}
return [expr {($sum % 10) == 0}]
}</
Driver:
<
49927398716
49927398717
Line 5,234 ⟶ 6,443:
puts [format "%s is %s" $testNumber \
[lindex {"NOT valid" "valid"} [luhn $testNumber]]]
}</
{{out}}
<pre>
Line 5,244 ⟶ 6,453:
=={{header|Terraform}}==
<
type = "string"
}
Line 5,262 ⟶ 6,471:
output "valid" {
value = local.check == 0
}</
{{Out}}
<pre>$ terraform apply
Line 5,282 ⟶ 6,491:
=={{header|TI-83 BASIC}}==
<
:Disp "ENTER NUMBER"
:Input Str1
Line 5,307 ⟶ 6,516:
:Disp "BAD CARD"
:End
</syntaxhighlight>
=={{header|Transact-SQL}}==
<syntaxhighlight 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>
=={{header|TUSCRIPT}}==
<
MODE DATA
$$ SET cardnumbers=*
Line 5,374 ⟶ 6,583:
PRINT c,"false"
ENDIF
ENDLOOP</
{{out}}
<pre>
Line 5,385 ⟶ 6,594:
=={{header|TXR}}==
<
(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)</
<pre>$ txr luhn.txr luhn.txt
Line 5,410 ⟶ 6,619:
{{works with|bash}}
{{works with|ksh}}
<
typeset n p s t=('0123456789' '0516273849')
while ((-n<${#1})); do
Line 5,425 ⟶ 6,634:
echo $c is valid
fi
done</
Notes:
Line 5,439 ⟶ 6,648:
=={{header|Ursala}}==
<
#import nat
luhn = %nP; %np*hxiNCNCS; not remainder\10+ //sum:-0@DrlrHK32 ~&iK27K28TK25 iota10</
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:
<
test = luhn* <49927398716,49927398717,1234567812345678,1234567812345670></
{{out}}
<pre>
Line 5,466 ⟶ 6,675:
=={{header|VBA}}==
<syntaxhighlight lang="vb">
Option Explicit
Line 5,493 ⟶ 6,702:
Luhn = "invalid"
End If
End Function</
{{out}}
<pre>Number 49927398716 is valid
Line 5,501 ⟶ 6,710:
=={{header|VBScript}}==
<
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")</
{{out}}
Line 5,543 ⟶ 6,752:
=={{header|Visual Basic}}==
{{works with|Visual Basic|VB6 Standard}}
<
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</
Test:
<
Debug.Assert LuhnCheckPassed("49927398716")
Debug.Assert Not LuhnCheckPassed("49927398717")
Debug.Assert Not LuhnCheckPassed("1234567812345678")
Debug.Assert LuhnCheckPassed("1234567812345670")
End Sub</
=={{header|Visual Basic .NET}}==
<syntaxhighlight lang="visual basic .net">
Imports System.Linq
Function ValidLuhn(value As String)
Line 5,579 ⟶ 6,788:
Console.WriteLine(ValidLuhn("1234567812345670"))
End Sub
</syntaxhighlight>
{{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-
<
import "./
var luhn = Fn.new { |s|
Line 5,611 ⟶ 6,860:
for (test in tests) {
var ans = (luhn.call(test)) ? "pass" : "fail"
}</
{{out}}
Line 5,623 ⟶ 6,872:
=={{header|Xojo}}==
<
//
// Confirm the digits are really, well, digits
Line 5,658 ⟶ 6,907:
return Modulus10( digits ) = checkDigit
End Function
</syntaxhighlight>
{{out}}
<pre>
Line 5,668 ⟶ 6,917:
=={{header|XPL0}}==
<
func Valid(Str); \Return 'true' if digits in Str pass Luhn test
Line 5,699 ⟶ 6,948:
CrLf(0);
];
]</
{{out}}
Line 5,710 ⟶ 6,959:
=={{header|zkl}}==
<
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)
}</
<
.apply(luhnTest).println();</
{{out}}
<pre>
Line 5,722 ⟶ 6,971:
=={{header|ZX Spectrum Basic}}==
<
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>
{{out}}
<pre>
|