Luhn test of credit card numbers: Difference between revisions

m
(→‎{{header|jq}}: versions)
 
(38 intermediate revisions by 23 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}}==
 
<langsyntaxhighlight lang="rebol">digits: function [n][
res: new []
while -> n > 0 [
Line 1,089 ⟶ 1,167:
print luhn? 1234567812345678
print luhn? 1234567812345670
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,099 ⟶ 1,177:
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">; Originally submitted by Laszlo:
; http://www.autohotkey.com/forum/post-229412.html#229412
 
Line 1,117 ⟶ 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,144 ⟶ 1,222:
EndIf
EndFunc ;==>checkLuhn
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,153 ⟶ 1,231:
 
=={{header|AWK}}==
<langsyntaxhighlight lang="awk">#!/usr/bin/awk -f
BEGIN {
A[1] = 49927398716;
Line 1,176 ⟶ 1,254:
}
return ((s%10)==0);
}</langsyntaxhighlight>
{{out}}
<pre>isLuhn(1234567812345670): 1
Line 1,187 ⟶ 1,265:
 
=={{header|Bash}}==
<langsyntaxhighlight lang="bash">#!/bin/bash
 
function luhn_validate # <numeric-string>
Line 1,226 ⟶ 1,304:
print_result "49927398717"
print_result "1234567812345678"
print_result "1234567812345670"</langsyntaxhighlight>
 
{{out}}
Line 1,234 ⟶ 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
Line 1,270 ⟶ 1,593:
goto :EOF
)
goto digit_loop</langsyntaxhighlight>
{{Out}}
<pre>>luhn.bat
Line 1,281 ⟶ 1,604:
 
=={{header|BBC BASIC}}==
<langsyntaxhighlight lang="bbcbasic"> FOR card% = 1 TO 4
READ cardnumber$
IF FNluhn(cardnumber$) THEN
Line 1,305 ⟶ 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,333 ⟶ 1,656:
l(49927398717)
l(1234567812345678)
l(1234567812345670)</langsyntaxhighlight>
 
{{Out}}
Line 1,342 ⟶ 1,665:
 
=={{header|BCPL}}==
<langsyntaxhighlight lang="bcpl">get "libhdr"
 
let luhn(s) = valof
Line 1,362 ⟶ 1,685:
show("1234567812345678")
show("1234567812345670")
$)</langsyntaxhighlight>
{{out}}
<pre>49927398716: pass
Line 1,371 ⟶ 1,694:
=={{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,380 ⟶ 1,703:
>:#,_@
11
</syntaxhighlight>
</lang>
The labelled points (1 to 11) are:
1. Read in input until number greater than 10,
Line 1,413 ⟶ 1,736:
 
=={{header|BQN}}==
<langsyntaxhighlight lang="bqn">Luhn ← (0=10|⊢)∘(+´(10|⊢)+⊢≥10˙)∘(⊢×≠⥊1‿2˙)∘(⌽•Fmt-'0'˙)
 
(⍉⊢≍Luhn¨) ⟨49927398716,49927398717,1234567812345678,1234567812345670⟩</langsyntaxhighlight>
{{out}}
<pre>┌─
Line 1,425 ⟶ 1,748:
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat"> ( luhn
= sum odd even
. 0:?sum
Line 1,449 ⟶ 1,772:
& test$1234567812345678
& test$1234567812345670
& ;</langsyntaxhighlight>
{{out}}
<pre>49927398716 : true
Line 1,458 ⟶ 1,781:
=={{header|Brainf***}}==
 
<syntaxhighlight lang="text">>>>>>>>>>+>,----------[ READ CHARACTERS UNTIL \N AND
>++++++++[<----->-]<++>>>>>>+>,----------] SUBTRACT ASCII 0 FROM EACH
<-<<<<<<< GO TO LAST DIGIT
Line 1,492 ⟶ 1,815:
<[<<.<---.<+++++..<] IF ZERO PASS
++++++++++. NEWLINE
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,505 ⟶ 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,538 ⟶ 1,916:
 
return 0;
}</langsyntaxhighlight>{{out}}
49927398716 ok
49927398717 not ok
Line 1,548 ⟶ 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,576 ⟶ 1,954:
}
}
</syntaxhighlight>
</lang>
<pre>
49927398716 is valid
Line 1,586 ⟶ 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,629 ⟶ 2,007:
}
}
}</langsyntaxhighlight>
<pre>
49927398716 is valid
Line 1,638 ⟶ 2,016:
 
A solution without using LINQ, works for all versions of .NET.
<langsyntaxhighlight lang="csharp">
using System;
namespace Luhn_Test
Line 1,689 ⟶ 2,067:
}
}
</syntaxhighlight>
</lang>
<pre>
1234567812345670 is Valid.
Line 1,698 ⟶ 2,076:
 
A solution optimized for readability:
<langsyntaxhighlight lang="csharp">
using System;
using System.Linq;
Line 1,721 ⟶ 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,755 ⟶ 2,133:
}
}
</syntaxhighlight>
</lang>
<pre>
49927398716
Line 1,768 ⟶ 2,146:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
using namespace std;
 
Line 1,810 ⟶ 2,188:
}
return 0;
}</langsyntaxhighlight>
 
===C++11===
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <vector>
#include <algorithm>
Line 1,834 ⟶ 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,932 ⟶ 2,310:
return 0;
}
</syntaxhighlight>
</lang>
<pre>
true
Line 1,942 ⟶ 2,320:
=={{header|Caché ObjectScript}}==
 
<langsyntaxhighlight lang="cos">Class Utils.Check [ Abstract ]
{
 
Line 1,958 ⟶ 2,336:
}
 
}</langsyntaxhighlight>
{{out|Examples}}
<pre>USER>For { Read ccn Quit:ccn="" Write ": "_##class(Utils.Check).Luhn(ccn), ! }
Line 1,969 ⟶ 2,347:
 
=={{header|Ceylon}}==
<langsyntaxhighlight lang="ceylon">shared void run() {
value numbers = "49927398716
49927398717
Line 1,995 ⟶ 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 2,006 ⟶ 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,097 ⟶ 2,509:
goback
.
END PROGRAM LUHN.</langsyntaxhighlight>
 
{{out}}
Line 2,106 ⟶ 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,115 ⟶ 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,125 ⟶ 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,189 ⟶ 2,634:
test("49927398717");
test("1234567812345678");
test("1234567812345670");</langsyntaxhighlight>
 
{{out}}
Line 2,198 ⟶ 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,206 ⟶ 2,651:
 
cards = [49927398716, "49927398717", 1234567812345678, "1234567812345670"]
cards.each{ |i| puts "#{i}: #{luhn_valid?(i)}" }</langsyntaxhighlight>
{{out}}
<pre>49927398716: true
Line 2,216 ⟶ 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,228 ⟶ 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,249 ⟶ 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,313 ⟶ 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,333 ⟶ 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,349 ⟶ 2,942:
 
numbers = ~w(49927398716 49927398717 1234567812345678 1234567812345670)
for n <- numbers, do: IO.puts "#{n}: #{Luhn.valid?(n)}"</langsyntaxhighlight>
 
{{out}}
Line 2,360 ⟶ 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,378 ⟶ 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,412 ⟶ 3,004:
Numbers = ["49927398716", "49927398717", "1234567812345678", "1234567812345670"],
[io:fwrite("~s: ~p~n", [X, credit_card(X)]) || X <- Numbers].
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,425 ⟶ 3,017:
=={{header|Euphoria}}==
{{trans|C}}
<langsyntaxhighlight lang="euphoria">function luhn(sequence cc)
integer isOdd, oddSum, evenSum, digit
isOdd = 1
Line 2,451 ⟶ 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,467 ⟶ 3,059:
 
{{Works with|Office 365 betas 2021}}
<langsyntaxhighlight lang="lisp">luhnChecked
=LAMBDA(s,
LET(
Line 2,487 ⟶ 3,079:
)
)
)</langsyntaxhighlight>
 
and also assuming the following generic bindings in the Name Manager for the WorkBook:
 
<langsyntaxhighlight lang="lisp">CHARSROW
=LAMBDA(s,
MID(s,
Line 2,521 ⟶ 3,113:
)
)
)</langsyntaxhighlight>
 
{{Out}}
Line 2,555 ⟶ 3,147:
 
=={{header|F Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">let luhn (s:string) =
let rec g r c = function
| 0 -> r
Line 2,561 ⟶ 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,583 ⟶ 3,175:
: luhn? ( n -- ? )
luhn-digit 0 = ;
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,598 ⟶ 3,190:
 
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">: luhn ( addr len -- ? )
0 >r over + ( R: sum )
begin 1- 2dup <=
Line 2,615 ⟶ 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,654 ⟶ 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,714 ⟶ 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,723 ⟶ 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,736 ⟶ 3,362:
 
for n <- [49927398716, 49927398717, 1234567812345678, 1234567812345670]
println( n + ' is ' + (if is_luhn_valid(n) then 'valid' else 'invalid') )</langsyntaxhighlight>
 
{{out}}
Line 2,745 ⟶ 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,784 ⟶ 3,466:
Next
 
End</langsyntaxhighlight>
Output:
<pre>
Line 2,794 ⟶ 3,476:
 
=={{header|GAP}}==
<langsyntaxhighlight lang="gap">IsLuhn := function(n)
local c, d, i, j, r;
d := "0123456789";
Line 2,816 ⟶ 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,853 ⟶ 3,535:
fmt.Println(s, luhn(s))
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,863 ⟶ 3,545:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def checkLuhn(number) {
int total
(number as String).reverse().eachWithIndex { ch, index ->
Line 2,870 ⟶ 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,879 ⟶ 3,561:
[49927398716: true, 49927398717: false, 1234567812345678: false, 1234567812345670: true].each { number, expected ->
verifyLuhn number, expected
}</langsyntaxhighlight>
{{out}}
<pre>Checking: 49927398716 (true)
Line 2,887 ⟶ 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,918 ⟶ 3,600:
"1234567812345678",
"1234567812345670"
]</langsyntaxhighlight>
{{Out}}
<pre>("49927398716",True)
Line 2,926 ⟶ 3,608:
 
=={{header|HicEst}}==
<langsyntaxhighlight HicEstlang="hicest">CHARACTER numbers="49927398716 49927398717 1234567812345678 1234567812345670 "
 
DO nr = 1, 4
Line 2,941 ⟶ 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,949 ⟶ 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,963 ⟶ 3,645:
 
return (sum % 10 = 0,i)
end</langsyntaxhighlight>
 
{{out}}
Line 2,974 ⟶ 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 3,029 ⟶ 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 3,062 ⟶ 3,696:
return (s1 + s2) % 10 == 0;
}
}</langsyntaxhighlight>
{{out}}
<pre>true
Line 3,068 ⟶ 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 3,097 ⟶ 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 3,111 ⟶ 3,783:
// returns false
luhn10('4111111111111112')
</syntaxhighlight>
</lang>
 
Naive implementation
<langsyntaxhighlight lang="javascript">const lunhCheck = (str) => {
const sumDigit = (c) => (c < 10) ? c :
sumDigit( Math.trunc(c / 10) + (c % 10));
Line 3,128 ⟶ 3,800:
lunhCheck('1234567812345678'); // returns false
lunhCheck('1234567812345670'); // returns true
</syntaxhighlight>
</lang>
 
=={{header|jq}}==
Line 3,139 ⟶ 3,811:
support for very large external integers would be required.
 
<langsyntaxhighlight lang="jq">def luhn:
def odds: . as $in | reduce range(0; length) as $i
([]; if ($i % 2) == 0 then . + [$in[$i]] else . end);
Line 3,150 ⟶ 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 3,167 ⟶ 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 3,180 ⟶ 3,852:
for card in [49927398716, 49927398717, 1234567812345678, 1234567812345670]
println(luhntest(card) ? "PASS " : "FAIL ", card)
end</langsyntaxhighlight>
 
{{out}}
Line 3,190 ⟶ 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,238 ⟶ 3,910:
for (number in numbers)
println("${number.padEnd(16)} is ${if(checkLuhn(number)) "valid" else "invalid"}")
}</langsyntaxhighlight>
 
{{out}}
Line 3,250 ⟶ 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,261 ⟶ 3,932:
}
 
val .tests = h{
"49927398716": true,
"49927398717": false,
Line 3,272 ⟶ 3,943:
write .key, ": ", .pass
writeln if(.pass == .tests[.key]: ""; " (LUHN TEST FAILED)")
}</langsyntaxhighlight>
 
{{out}}
Line 3,282 ⟶ 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,305 ⟶ 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,338 ⟶ 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,365 ⟶ 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,394 ⟶ 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,427 ⟶ 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,470 ⟶ 4,140:
end while
}
Checkit</syntaxhighlight>
</lang>
{{out}}
<pre>49927398716 = True
Line 3,477 ⟶ 4,146:
1234567812345678 = False
1234567812345670 = True</pre>
 
=={{header|MACRO-11}}==
<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}}==
<langsyntaxhighlight Mathematicalang="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,508 ⟶ 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,517 ⟶ 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,523 ⟶ 4,246:
 
(49927398716 49927398717 1234567812345678 1234567812345670)
(dup print! " " print! luhn? puts!) foreach</langsyntaxhighlight>
{{out}}
<pre>
Line 3,533 ⟶ 4,256:
 
=={{header|MiniScript}}==
<langsyntaxhighlight MiniScriptlang="miniscript">isValid = function(s)
sum = 0
odd = true
Line 3,552 ⟶ 4,275:
test "49927398717"
test "1234567812345678"
test "1234567812345670"</langsyntaxhighlight>
 
{{out}}
Line 3,561 ⟶ 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,582 ⟶ 4,305:
=={{header|Nanoquery}}==
{{trans|Java}}
<langsyntaxhighlight Nanoquerylang="nanoquery">def reverse_str(string)
to_return = ""
 
Line 3,613 ⟶ 4,336:
println luhnTest("49927398717")
println luhnTest("1234567812345678")
println luhnTest("1234567812345670")</langsyntaxhighlight>
{{out}}
<pre>true
Line 3,621 ⟶ 4,344:
 
=={{header|NetRexx}}==
{{trans|REXX}}<langsyntaxhighlight lang="netrexx">
class LuhnTest
 
Line 3,648 ⟶ 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,662 ⟶ 4,385:
for cc in ["49927398716", "49927398717", "1234567812345678", "1234567812345670"]:
echo cc, ' ', luhn(cc)</langsyntaxhighlight>
 
{{out}}
Line 3,671 ⟶ 4,394:
 
=={{header|Objeck}}==
<langsyntaxhighlight lang="objeck">bundle Default {
class Luhn {
function : IsValid(cc : String) ~ Bool {
Line 3,699 ⟶ 4,422:
}
}
}</langsyntaxhighlight>
 
=={{header|Objective-C}}==
<langsyntaxhighlight lang="objc">- (NSArray *) toCharArray {
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[self length]];
Line 3,739 ⟶ 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,750 ⟶ 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,773 ⟶ 4,496:
isluhn('1234567812345670')
ans = 1
</syntaxhighlight>
</lang>
 
=={{header|Oforth}}==
 
<langsyntaxhighlight Oforthlang="oforth">: luhnTest(n)
| s i |
n asString reverse ->s
Line 3,784 ⟶ 4,507:
i isEven ifTrue: [ 2 * dup 10 >= ifTrue: [ 9 - ] ] +
]
10 mod ==0 ; </langsyntaxhighlight>
 
{{out}}
Line 3,793 ⟶ 4,516:
 
=={{header|OpenEdge/Progress}}==
<langsyntaxhighlight lang="progress">FUNCTION fnLuhnAlgorithm RETURNS LOGICAL
(INPUT pcNumber AS CHARACTER):
/*------------------------------------------------------------------------------
Line 3,841 ⟶ 4,564:
RETURN FALSE.
 
END FUNCTION. /* fnLuhnAlgorithm */</langsyntaxhighlight>
 
{{out}}
Line 3,853 ⟶ 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,887 ⟶ 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,914 ⟶ 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,966 ⟶ 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,979 ⟶ 4,778:
# Test and display
map {print luhn($_), ": $_\n"}
qw(49927398716 49927398717 1234567812345678 1234567812345670);</langsyntaxhighlight>
 
{{out}}
Line 3,988 ⟶ 4,787:
 
=={{header|Phix}}==
<!--<langsyntaxhighlight Phixlang="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>
Line 4,004 ⟶ 4,803:
<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>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 4,015 ⟶ 4,814:
=={{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 4,030 ⟶ 4,829:
}
return $sum % 10 == 0;
}</langsyntaxhighlight>
{{out}}
<pre>49927398716 is valid
Line 4,038 ⟶ 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 4,045 ⟶ 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 4,052 ⟶ 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 4,065 ⟶ 4,894:
(flip (chop Num))
'(T NIL .) )
10 ) ) )</langsyntaxhighlight>
{{out}}
<pre>: (mapcar luhn (49927398716 49927398717 1234567812345678 1234567812345670))
Line 4,071 ⟶ 4,900:
 
=={{header|PL/I}}==
<langsyntaxhighlight lang="pli">test: procedure options (main);
 
declare (cardnumber, rcn) character (20) varying;
Line 4,094 ⟶ 4,923:
put skip edit (cardnumber, ' does not pass the Luhn test' )(a);
put skip list (s1 + s2);
end test;</langsyntaxhighlight>
 
{{out}}
Line 4,109 ⟶ 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 4,143 ⟶ 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 4,189 ⟶ 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,200 ⟶ 5,075:
=={{header|PowerBASIC}}==
{{trans|Visual Basic}}
<langsyntaxhighlight lang="powerbasic">#COMPILE EXE
#DIM ALL
#COMPILER PBCC 6
Line 4,229 ⟶ 5,104:
' this test is expected to pass:
CON.PRINT IIF$(LuhnCheckPassed("1234567812345670"), "passed", "failed")
END FUNCTION</langsyntaxhighlight>
{{out}}
<pre>passed
Line 4,237 ⟶ 5,112:
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Test-LuhnNumber
{
Line 4,298 ⟶ 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,320 ⟶ 5,195:
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">DataSection
Sample:
Data.s "49927398716"
Line 4,374 ⟶ 5,249:
Input()
CloseConsole()
EndIf</langsyntaxhighlight>
{{out}}
<pre>49927398716 is valid
Line 4,384 ⟶ 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,399 ⟶ 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,435 ⟶ 5,310:
 
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>[True, False, False, True]</pre>
Line 4,443 ⟶ 5,318:
and cycle lambdas rather than integers.
 
<langsyntaxhighlight lang="python">'''Luhn test of credit card numbers'''
 
from itertools import cycle
Line 4,481 ⟶ 5,356:
if __name__ == '__main__':
main()
</syntaxhighlight>
</lang>
{{Out}}
<pre>('49927398716', True)
Line 4,490 ⟶ 5,365:
===Procedural===
Without usingsum() and divmod() functions:
<langsyntaxhighlight lang="python">>>> def vérifLuhn(ch):
sum = 0
chParity = len(ch) % 2
Line 4,505 ⟶ 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,514 ⟶ 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,522 ⟶ 5,397:
=={{header|Quackery}}==
 
<langsyntaxhighlight Quackerylang="quackery"> [ 1 & ] is odd ( n --> b )
 
[ [] swap
Line 4,564 ⟶ 5,439:
else
[ say " invalid" ]
cr ]</langsyntaxhighlight>
 
{{out}}
Line 4,575 ⟶ 5,450:
=={{header|R}}==
 
<langsyntaxhighlight lang="rsplus">
is.luhn <- function(cc){
numbers <- as.numeric(rev(unlist(strsplit(cc,""))))
Line 4,583 ⟶ 5,458:
sapply(c("49927398716","49927398717","1234567812345678","1234567812345670"),is.luhn)
 
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,592 ⟶ 5,467:
=={{header|Racket}}==
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 4,605 ⟶ 5,480:
(map luhn-test '(49927398716 49927398717 1234567812345678 1234567812345670))
;; -> '(#t #f #f #t)
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 4,619 ⟶ 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,641 ⟶ 5,516:
is luhn-test(+$cc), $expected-result,
"$cc {$expected-result ?? 'passes' !! 'does not pass'} the Luhn test.";
}</langsyntaxhighlight>
 
{{out}}
Line 4,650 ⟶ 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,667 ⟶ 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,677 ⟶ 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,712 ⟶ 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,722 ⟶ 5,629:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">decimals(0)
 
test = ["49927398716", "49927398717", "1234567812345678", "1234567812345670"]
Line 4,780 ⟶ 5,687:
next
return sumarr
</syntaxhighlight>
</lang>
Output:
<pre>
Line 4,787 ⟶ 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,798 ⟶ 5,741:
 
["49927398716", "49927398717", "1234567812345678", "1234567812345670"].map{ |i| luhn_valid?(i) }
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,804 ⟶ 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,812 ⟶ 5,755:
 
cards = [49927398716, "49927398717", 1234567812345678, "1234567812345670"]
cards.each{ |i| puts "#{i}: #{luhn_valid?(i)}" }</langsyntaxhighlight>
 
{{out}}
Line 4,821 ⟶ 5,764:
 
=={{header|Run BASIC}}==
<langsyntaxhighlight lang="runbasic">card$(1) = "49927398716"
card$(2) = "49927398717"
card$(3) = "1234567812345678"
Line 4,837 ⟶ 5,780:
next i
if chkSum mod 10 = 0 then luhn$ = "True" else luhn$ = "False"
end function</langsyntaxhighlight>
{{out}}
<pre>49927398716 True
Line 4,845 ⟶ 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,893 ⟶ 5,836:
assert_eq!(validate_isin("FR0000988040"), true);
}
}</langsyntaxhighlight>
{{out}}
<pre>49927398716: true
Line 4,904 ⟶ 5,847:
 
===Functional style===
<langsyntaxhighlight lang="scala">object Luhn {
private def parse(s: String): Seq[Int] = s.map{c =>
assert(c.isDigit)
Line 4,929 ⟶ 5,872:
assert(Luhn.validate(n) == expected)
}
}</langsyntaxhighlight>
{{out}}
<pre>49927398716 true
Line 4,937 ⟶ 5,880:
 
===Imperative style===
<langsyntaxhighlight lang="scala"> def luhnTest1(number: String): Boolean = {
var (odd, sum) = (true, 0)
 
Line 4,946 ⟶ 5,889:
}
sum % 10 == 0
}</langsyntaxhighlight>
 
=={{header|Scheme}}==
<langsyntaxhighlight lang="scheme">(define luhn
(lambda (n)
(let loop ((number n)
Line 4,962 ⟶ 5,905:
(remainder number 10)
(let ((part (* 2 (remainder number 10))))
(+ (remainder part 10) (quotient part 10))))))))))</langsyntaxhighlight>
{{out}}
<pre>
Line 4,970 ⟶ 5,913:
 
=={{header|sed}}==
<langsyntaxhighlight lang="sed"># Split number into double evens and odds
s/.*/&: /
: split
Line 4,997 ⟶ 5,940:
/0:/!a\
Fail
d</langsyntaxhighlight>
 
{{out}}
Line 5,014 ⟶ 5,957:
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const func boolean: luhnTest (in string: cardNumber) is func
Line 5,045 ⟶ 5,988:
writeln(cardNumber <& ": " <& luhnTest(cardNumber));
end for;
end func;</langsyntaxhighlight>
 
{{out}}
Line 5,056 ⟶ 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 5,071 ⟶ 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 5,087 ⟶ 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 5,111 ⟶ 6,054:
 
(map (function luhn?) ["49927398716" "49927398717" "1234567812345678" "1234567812345670"])
</syntaxhighlight>
</lang>
 
{{out}}
Line 5,126 ⟶ 6,069:
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">func luhn (n) {
static a = {|j| (2*j // 10) + (2*j % 10) }.map(^10)
 
Line 5,138 ⟶ 6,081:
for n in [49927398716, 49927398717, 1234567812345678, 1234567812345670] {
say [n, luhn(n)]
}</langsyntaxhighlight>
 
{{out}}
Line 5,148 ⟶ 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 5,178 ⟶ 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,237 ⟶ 6,247:
Do_Test("1234567812345670");
Do_Test("123456781234567D");
end Luhn;</langsyntaxhighlight>
{{out}}
<pre>49927398716 is valid.
Line 5,248 ⟶ 6,258:
{{works with|Db2 LUW}}
With SQL PL:
<langsyntaxhighlight lang="sql pl">
--#SET TERMINATOR @
 
Line 5,325 ⟶ 6,335:
END
@
</syntaxhighlight>
</lang>
Output:
<pre>
Line 5,374 ⟶ 6,384:
 
=={{header|Standard ML}}==
<langsyntaxhighlight lang="sml">local
fun revDigits 0 = []
| revDigits n = (n mod 10) :: revDigits (n div 10)
Line 5,395 ⟶ 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,407 ⟶ 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,423 ⟶ 6,433:
}
return [expr {($sum % 10) == 0}]
}</langsyntaxhighlight>
Driver:
<langsyntaxhighlight lang="tcl">foreach testNumber {
49927398716
49927398717
Line 5,433 ⟶ 6,443:
puts [format "%s is %s" $testNumber \
[lindex {"NOT valid" "valid"} [luhn $testNumber]]]
}</langsyntaxhighlight>
{{out}}
<pre>
Line 5,443 ⟶ 6,453:
 
=={{header|Terraform}}==
<langsyntaxhighlight lang="hcl">variable number {
type = "string"
}
Line 5,461 ⟶ 6,471:
output "valid" {
value = local.check == 0
}</langsyntaxhighlight>
{{Out}}
<pre>$ terraform apply
Line 5,481 ⟶ 6,491:
 
=={{header|TI-83 BASIC}}==
<langsyntaxhighlight lang="ti83b">PROGRAM:LUHN
:Disp "ENTER NUMBER"
:Input Str1
Line 5,506 ⟶ 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,530 ⟶ 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,573 ⟶ 6,583:
PRINT c,"false"
ENDIF
ENDLOOP</langsyntaxhighlight>
{{out}}
<pre>
Line 5,584 ⟶ 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,598 ⟶ 6,608:
@ccnumber -> @(if (luhn (int-str ccnumber 10)) "good" "bad")
@(end)
@(end)</langsyntaxhighlight>
 
<pre>$ txr luhn.txr luhn.txt
Line 5,609 ⟶ 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,624 ⟶ 6,634:
echo $c is valid
fi
done</langsyntaxhighlight>
 
Notes:
Line 5,638 ⟶ 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,656 ⟶ 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,665 ⟶ 6,675:
 
=={{header|VBA}}==
<syntaxhighlight lang="vb">
<lang VB>
Option Explicit
 
Line 5,692 ⟶ 6,702:
Luhn = "invalid"
End If
End Function</langsyntaxhighlight>
{{out}}
<pre>Number 49927398716 is valid
Line 5,700 ⟶ 6,710:
 
=={{header|VBScript}}==
<langsyntaxhighlight VBScriptlang="vbscript">Function Luhn_Test(cc)
cc = RevString(cc)
s1 = 0
Line 5,732 ⟶ 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,742 ⟶ 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,756 ⟶ 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,778 ⟶ 6,788:
Console.WriteLine(ValidLuhn("1234567812345670"))
End Sub
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,785 ⟶ 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,810 ⟶ 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,822 ⟶ 6,872:
 
=={{header|Xojo}}==
<langsyntaxhighlight lang="xojo">Public Function Modulus10(digits As String) as String
//
// Confirm the digits are really, well, digits
Line 5,857 ⟶ 6,907:
return Modulus10( digits ) = checkDigit
End Function
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,867 ⟶ 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,898 ⟶ 6,948:
CrLf(0);
];
]</langsyntaxhighlight>
 
{{out}}
Line 5,909 ⟶ 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,921 ⟶ 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,945 ⟶ 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