# The Luhn algorithm for verifying credit card numbers, etc

### Challenge

Write the shortest program or function to calculate the Luhn Algorithm for verifying (credit card) numbers.

### Luhn algorithm explained

From RosettaCode, this algorithm for the purposes of this challenge is specified as such, with the example input of 49927398716:

Reverse the digits, make an array:
6, 1, 7, 8, 9, 3, 7, 2, 9, 9, 4
Double the numbers in odd indexes:
6, 2, 7, 16, 9, 6, 7, 4, 9, 18, 4
Sum the digits in each number:
6, 2, 7, 7, 9, 6, 7, 4, 9, 9, 4
Sum all of the numbers:
6 + 2 + 7 + 7 + 9 + 6 + 7 + 4 + 9 + 9 + 4 = 70
If the sum modulo 10 is 0, then the number is valid:
70 % 10 = 0 => valid


### IO Rules

Input: A string or number (your choice), in your language's input/output format of choice

Output: A truthy or falsy value, respectively, indicating whether or not the input is valid according to the test above.

### Notes / Tips

• Try not to accidentally post your own credit card or account numbers, if you use them to test :)

• If the input is invalid and impossible to process with the specified algorithm (i.e, too short to work with), you can do whatever you want, including blow up my computer.

• However, the previous bullet does not mean that your language can do whatever it wants with Numbers that are too large for it to handle. If your language isn't capable of handling a test case, then consider taking a string as input.

### Examples

The following examples were validated with this Python script; if you think one is wrong or have a question, just ping @cat.

49927398716      True
49927398717      False
1234567812345670 True
1234567812345678 False
79927398710      False
79927398711      False
79927398712      False
79927398713      True
79927398714      False
79927398715      False
79927398716      False
79927398717      False
79927398718      False
79927398719      False
374652346956782346957823694857692364857368475368 True
374652346956782346957823694857692364857387456834 False
8 False **
0 True  **


** according to the Python implementation, but you may do anything because these are too short to be eligible by a strict adherence to the specification.

If any of the above invalidates existing answers (though I believe that should not be possible), then those answers are stil valid. However, new answers, in order to be valid, should follow the specification above.

var QUESTION_ID=22,OVERRIDE_USER=73772;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

# Jelly, 14 bytes

DUḤJḤ$¦DS$€S⁵ḍ


Try it online!

Explanation:

D              get digits
U             reverse array
JḤ$for every other index, Ḥ ¦ double the value € for each value, D$     get the digits

## Algorithm

1. Let l1 be a list storing each digit in reverse order.
2. Let s be 0.
3. Let l2 be an empty list.
4. If l1 is empty, go to step 9.
5. Pop one value from l1 and let it be n. Push n*(s+1) onto l2.
6. If last value on l2 is more than 9, subtract 9 from it.
7. Let s be 1-s.
8. Go to step 4.
9. Calculate (sum of each item in l2)%10.
10. If step 9 resulted in 0, the program returns truthy; otherwise falsey.

# getchar() unil EOF
# substract 48 for each character
.w0.-.i.c\001.+.aXX.z
# at this point stack is -1, [0-9], ..., [0-9], 48.
# add 1 to -1 so: 0, ..., 48.
# move 0 to bottom: [0-9], ..., 48, 0.
.a\001.+.t.v.m.vXX.z
# loop
# every time loop begins, bottom should be [01].
# also heap should be same as bottom.
.aQJ.zXX.z
# to: [0-9], [01], ..., 48, ..., [01]... I think
# WTF did I do here?
.a.v.m.v.c.m.+.c.t.-.m.v.t.v.m.-.mXX.z
# multiply [0-9] to ([01]+1)
.a\001.+.!XX.z
# subtract 9 if more than 9
.a.c\011.x\011.-XX.aXX.z
# move top to bottom, replacing it
.a.t.v.s.m.vXX.z
# alt for [01] xor 1; subtract from 1
# then move to bottom
.a\001.-.t.v.m.vXX.z
# break if top equals 48
.a.c0.aXX.z
# make 48 to 10, then remove botton [01]
# OBTW reversed, but whatever
.a\046.-.v.sXX.z
# loop
[email protected]
# if size is 1; then
.a.t.c.c.ZXX.z
# modulo by 10
.a.m\012.%XX.z
# if it is 0; then print Y and exit; else exit; fi
.a.w.d.aY.o.d.AXX.z
# fi; push (pop+pop)
.a.m.+
# end of loop
[email protected]


# Vyxal, 12 11 bytes

-1 byte thanks to @lyxal reminding me about multibyte lambdas.

ṘÞTf‡d∑ẇ∑₀Ḋ


Try it Online!

Explanation:

             # Implicit input
Ṙ            # Reverse
ÞT          # Transpose
f         # Flatten list
‡  ẇ     # For every second element:
d       #   Double
∑      #   Sum digits
∑    # Sum all elements
₀Ḋ  # x % 10 == 0?
# Implicit output

• use a multi byte lambda for 11 bytes May 7, 2021 at 12:50
• @lyxal Wow. I can't believe I forgot those existed. Thanks! May 7, 2021 at 12:56

# Julia 1.0, 51 50 bytes

~=digits;!n=(k=~n;k[2:2:end]*=2;sum(sum,.~k)%10<1)


Try it online!

# GNU sed, 140 bytes

(including +1 for the -r flag)

s/^(..)*.$/0&/ s/(.)./\1x&/g s/x[5-9]/1&/g s/[0x]//g s/[789]/&6/g s/[456]/&3/g s/[369]/&11/g s/[258]/&1/g s/.{10}//g s/.+/false/ s/^$/true/


Sed is almost never the most natural language for arithmetic, but here we go:

#!/bin/sed -rf

s/^(..)*.$/0&/ # double every other digit s/(.)./\1x&/g # add carry (converts mod-9 to mod-10) s/x[5-9]/1&/g # convert sum to unary s/[0x]//g s/[789]/&6/g s/[456]/&3/g s/[369]/&11/g s/[258]/&1/g # remove whole tens s/.{10}//g # output 'true' or false s/.+/false/ s/^$/true/


## PHP - 136 characters

function t($c){foreach($a=str_split(strrev($c)) as$k=>&$v){$v=array_sum(str_split(($k % 2)!==0?2*$v:$v));}return !(array_sum($a)% 10);}


# MATL, 23 20 bytes (non competing)

P!Utn:2X\!*t9>+s10\~


Try it online!

Outputs 1 for a valid number, 0 otherwise.

Saved three bytes thanks to Luis Mendo's suggestions.

## Explanation

P       % flip the order of elements
!       % transpose into column vector
U       % convert char matrix to numeric
t       % duplicate the vector
n       % find the length
:       % create a new vector length n (1, 2, 3, ... n)
2       % number literal
X\      % take it mod 2, to make the new vector (1, 2, 1, ..., (n-1) mod 2 +1)
!       % transpose
*       % element-wise product
t       % duplicate
9       % push 9
>       % 1 if it is greater than 9
+       % add the vectors, this makes the last digit of each the same as the sum of the digits
10      % number literal
\       % mod 10
~       % logical 'not' (element-wise)
% (implicit) convert to string and display


# K (oK), 28 bytes

Solution:

~10!+/48!,/$(1+2!!#x)*48!|x:  Try it online! Examples: ~10!+/48!,/$(1+2!!#x)*48!|x:"1234567812345670"
1
~10!+/48!,/$(1+2!!#x)*48!|x:"1234567812345678" 0  Explanation: ~10!+/48!,/$(1+2!!#x)*48!|x: / the solution
x: / save input as variable x
|   / reverse it
48!    / mod with 48 (converts ascii -> int)
(       )*       / multiply with stuff in brackets
#x         / length of x
!           / til, the range 0..x-1
2!            / mod with 2 (0 1 2 3 -> 0 1 0 1)
1+              / add 1 (0 1 0 1 -> 1 2 1 2)
$/ convert to string ,/ / flatten string 48! / convert this into integers +/ / sum over the list 10! / modulo 10 ~ / negate (so 1 for truthy, 0 for falsy)  Extra: A couple of 30-byte solutions in K4, not quite as short... ~.*|$+/,/10\:'((#x)#1 2)*.:'x:
~.*|$+/.:'',/$((#x)#1 2)*.:'x:


# Pyt, 20 bytes

ĐḶ⌊⁺⇹ą↔⇹ř⁻2%⁺*ŚƩ1ᴇ%¬


Explanation:

                        Implicit input
Đ                       Duplicate input
Ḷ⌊⁺                    Get length of integer in base-10 (floor(log_10(input))+1)
⇹                   Swap top two on stack
ą↔                 Convert input to an array of digits, and reverse
⇹                Swap top two on stack
ř⁻              Push [0,1,2,...,floor(log_10(input))]
2%            Take previous array element-wise mod 2
⁺           Increment each element of the array
*          Elementwise multiplication of the arrays
Ś         Elementwise sum of digits
Ʃ        Sum up array
1ᴇ%     Mod 10
¬    Negate (this returns false if not 0, and true otherwise)


Try it online!

# Kotlin, 77 bytes

mapIndexed{i,c->(""+(2-(length%2 xor i%2))*(c-'0')).sumBy{it-'0'}}.sum()%10<1


## Beautified

mapIndexed { i, c ->
("" + (2 - (length % 2 xor i % 2)) * (c - '0')).sumBy { it - '0' }
}.sum() % 10 < 1


## Test

data class Test(val input: String, val output: Boolean)

val tests = listOf(
Test("49927398716", true),
Test("49927398717", false),
Test("1234567812345670", true),
Test("1234567812345678", false),
Test("79927398710", false),
Test("79927398711", false),
Test("79927398712", false),
Test("79927398713", true),
Test("79927398714", false),
Test("79927398715", false),
Test("79927398716", false),
Test("79927398717", false),
Test("79927398718", false),
Test("79927398719", false),
Test("374652346956782346957823694857692364857368475368", true),
Test("374652346956782346957823694857692364857387456834", false),
Test("8", false),
Test("0", true)
)

fun String.f() =
mapIndexed{i,c->(""+(2-(length%2 xor i%2))*(c-'0')).sumBy{it-'0'}}.sum()%10<1
fun main(args: Array<String>) {
for ((input, expectedOut) in tests) {
val actualOut = input.f()
if (actualOut != expectedOut) {
System.err.println("$input$expectedOut $actualOut") } } }  ## TIO TryItOnline # Dart, 120 bytes f(s,{i=0})=>s.split('').reversed.map(int.parse).map((n)=>i++%2>0?n*2:n).map((n)=>n>9?n-10+1:n).fold(0,(p,e)=>p+e)%10==0;  Try it online! # Perl 6, 37 bytes (*.flip.comb >>*>>[1,2]).comb.sum%%10  Try it online! A Whatever lambda that takes a number and returns a boolean. ### Explanation:  *.flip # Reverse the number .comb # Split to list of digits >>*>> # Multiply each element by: [1,2] # The list 1,2,1,2,1,2... ( ).comb # Split the list to a list of digits .sum # Get the digit sum %%10 # Return if it is divisible by 10  Julia, 67 bytes x=digits(n) sum(x[1:2:end])+sum(reduce(vcat,digits.(x[2:2:end]*2)))  # MathGolf, 11 bytes ▒xôï¥)*Σ+♂÷  Try it online! At least I tied with Jelly, I can't really see a way to remove a byte from this. ## Explanation ▒ split to list of chars/digits x reverse int/array/string ô start block of length 6 (for-each) ï index of current loop ¥ modulo 2 ) increment * pop a, b : push(a*b) Σ digit sum + add to the counter (implicitly calculates 0+x when stack only has one element) Block ends here ♂ push 10 ÷ is divisible  # Haskell, 73 bytes i#0=0 i#n|m<-mod n 10=i*(m+sum[-9|m>4])+m+(1-i)#div n 10 f n=mod(0#n)10<1  Try it online! # APL(NARS), 37 chars, 74 bytes {0=10∣+/{+/10 10⊤⍵}¨v+v×0=2∣⍳≢v←⌽⍎¨⍵}  test:  f←{0=10∣+/{+/10 10⊤⍵}¨v+v×0=2∣⍳≢v←⌽⍎¨⍵} f '1234567812345670' 1 f '49927398717' 0 f '1234567812345678' 0 f '79927398710' 0 f '79927398719' 0 f '374652346956782346957823694857692364857368475368' 1 f '374652346956782346957823694857692364857387456834' 0 f ,'8' 0 f ,'0' 1  comment: {0=10∣+/{+/10 10⊤⍵}¨v+v×0=2∣⍳≢v←⌽⍎¨⍵} ⍎¨⍵ for each element of ⍵ (that would be char digits) convert in int v←⌽ reverse the array result of above, and assign it to variable v ⍳≢ produce all index of above v that are 1..≢v 0=2∣ produce one array of boolean where 0 means even index, 1 odd v+v× multipy that array for v itself (means get only odd ones the other 0) and sum it to v (so we have v with elements index odd duplicate) {+/10 10⊤⍵}¨ convert each element of the array of 2 digits base 10 than sum 10∣+/ sum all element mod 10 0= if result is 0 return 1 (true), else return 0 (false)  # Japt v2.0a0, 14 bytes ¬ÔxÈ*ÒYu)ìxÃvA  The first byte can be removed if I took input as array of chars. Try it ¬ //Split (implicit) input into list of chars Ô //Reverse xÈ //Get the sum of every char after passing through the following function * // Multiply the element ÒYu) // By the index modulus 2 plus 1 (Odd -> 2, Even -> 2) ìx // And take the sum of the digits Ã //Close function vA //And check if result is divisible by 10  • Oh, didn't see you'd posted this before I fixed mine. Don't forget, you only have 'til Tuesday to post 3 more solutions and qualify for the additional 300 rep bounty. Mar 28, 2019 at 17:23 # PHP, 83 82 bytes foreach(str_split(strrev($argn))as$x=>$d)$m+=$d+($d%10+$d/5|0)*$x&=1;echo!($m%10);


As standalone program, call with php -F. Input is STDIN, output is to STDOUT as bool (1 or empty).

$echo 49927398716|php -F luhn.php 1$ echo 49927398717|php -F luhn.php

$echo 1234567812345670|php -F luhn.php 1  Verify all test cases # R, 46 bytes function(x,y=rev(x)*1:2)!sum(y%%10+y%/%10)%%10  Try it online! # Husk, 15 13 bytes Edit: -2 bytes thanks to Razetime ¬→dṁΣzod*¢ḣ2↔  Try it online! ¬ # logical NOT of →d # last decimal digit of ṁΣ # sum of sums of results of z # zipping two lists together ¢ḣ2 # list 1: [1,2] repeated ↔ # list 2: input, reversed o # using these two functions: d* # decimal digits of product  • 13 bytes using cycle Dec 11, 2020 at 3:50 • Nice! Thanks! Another new function used for the first time... Dec 11, 2020 at 6:45 # dc, 61 bytes [A~rdZ1<S]dsSxz2%1=0[2*SaSaz1<LLaLalSx]dsLx[+z1<L]dsLxA%0=0zp  Try it online! [A~rdZ1<S]dsSx # split: take quotient and remainder by 10, rotate quotient to top z2%1=0 # if odd length, prepend 0 (I think. I poked it until it worked) [2*SaSaz1<LLaLalSx]dsLx # double every other number, split them all [+z1<L]dsLx # sum everything A%0=0zp # if n%10 == 0, print 1; else, print 0  The last line works because: 1. Each register holds 0 by default 2. Comparisons attempt to execute whatever's in the specified register (0 here) 3. Executing a number simply returns the number So if we execute the contents of register 0, then we have one item on the stack: 0. Otherwise, the stack is empty. Use z to convert this to a 0 or 1. ## C (gcc), 126 110 bytes -16 bytes thanks to ceilingcat #define e s[1][i] c,b;main(i,s)char**s;{for(i=strlen(s[1]);i--;b+=e-=e/10?9:0)e-=48,e*=c++%2+1;return!(b%10);}  Input is taken through an argument and output uses exit codes, 0 for false and 1 for true Explanation: #define e s[1][i] c,b; main(i,s) // i, c, and b are ints for program use char**s; // argv, used for input { for(i=strlen(s[1]); i--; b+=e-=e/10?9:0) // iterate backwards through string, and add to the total (b) while also doing the digit add e-=48, // subtract '0' e*=c++%2+1; // double each odd index return!(b%10); // check if b ends in 0 and return that }  • Suggest e<<=c++%2 instead of e*=c++%2+1 Dec 25, 2020 at 2:33 # Vyxal, 16 bytes ₀τƛ¥₂ßd&›₀τ∑;∑₀Ḋ  Try it Online! ₀τ # Digits... ƛ ; # Map ¥₂ # If register is even ßd # Double &› # Increment register ₀τ # Digits... ∑ # Sum ∑ # Sum of all... ₀Ḋ # is divisible by 10?  # Fig, $$\10\log_{256}(96)\approx\$$ 8.231 bytes ]SeSn2@h$f


Try it online!

Outputs using inverted logic: positive integer for falsey, 0 for truthy

]SeSn2@h$f f # Digits of number$  # Reverse
n2@    # For every other item in the list
h   # Unhalve (double)
eS       # Digit sum of each
S         # Sum
]          # Take the last digit (equivalent to mod 10)


# Vyxal, 8 bytes

fṘ⁽dẇṠ∑t


Try it Online!

Outputs 0 for truthy, any positive integer for falsey.

## Explained

fṘ⁽dẇṠ∑t
fṘ       # reverse the list of digits of the input
⁽dẇ    # double each odd-indexed digit
Ṡ∑t # sum each number, and take the tail of the sum


# ><>, 39 37 bytes

00@:}2%1+$c%*:a%$9)++{1+$1l3=. n;a%0=  Try it online Explanation 00 # init sum and counter to 0 @:}2%1+ # set counter to 1 if even and 2 if odd$c%*                      # mod current number by 12 and multiply by counter
:a%$9)++ # sum digits and add to total sum {1+$        # increment counter
1l3=.   # jump to next row if done, else skip init on 1st row
n;a%0=                             # print sum mod 10 == 0


# Zsh, 52 bytes

for j (${(Oas::)1})((s+=++i%2?j:j*2.2%10)) <<<$s[-1]


Try it Online..

Parse input into array and reverse it: \${(Oas::)1}. Then iterate over the array elements.
0 is truthy, non-zero is falsy.

From my work, the Visa test number (4111 1111 1111 1111) is embedded in my brain.

Previous efforts: 55 bytes 61 bytes 72 bytes 77 bytes

# Thunno 2t!, 8 bytes

drŻɗ⁺×ʂS


Attempt This Online!

#### Or 10 bytes flagless:

drŻɗ⁺×ʂSt~


Attempt This Online!

#### Explanation

drŻɗ⁺×ʂSt~  # Implicit input
dr          # Cast to digits; reverse the list
Ż         # Without popping, push [0..length)
ɗ⁺       # Mod 2 of each; increment each
×      # Multiply elementwise
ʂ     # Sum the digits of each number
S    # Sum the resulting list
t   # Pop and push the last digit
~  # And check if this equals 0
# Implicit output


# Pyth, 19 bytes (non-competing)

Non-competing since Pyth is newer than this challenge.

!%s.esj*b@S2kT_jQTT


A program that takes input of a string on STDIN and prints True or False as appropriate.

How it works

!%s.esj*b@S2kT_jQTT  Program. Input: Q
jQT   Yield the base-10 representation of Q as a list, giving the digits
_      Reverse
.e                Enumerated map, with elements as b and indices as k:
S2           Yield [1, 2]
@  k          Modular indexing with k, yielding 1 for even indices and 2 for odd
indices
*b              Multiply by b
j      T         Yield the digits
s                 Sum
s                  Sum the resulting list
%                T  Modulo 10
!                    Logical not, yielding True for 0 and False otherwise
Implicitly print