| Bytes | Lang | Time | Link |
|---|---|---|---|
| 055 | Ruby | 221109T225252Z | Jordan |
| 010 | Vyxal 3 | 250506T092454Z | Themooni |
| 085 | Tcl | 171021T200435Z | sergiol |
| 077 | Python 3 | 110127T220704Z | Alexandr |
| 108 | PHP | 110127T225138Z | Champo |
| 8381 | Rust | 240806T150456Z | mousetai |
| 156 | Go | 240624T174718Z | bigyihsu |
| 082 | Forth gforth | 240701T131044Z | reffu |
| 181 | Rust | 240624T182250Z | bigyihsu |
| 071 | bash | 190323T040536Z | roblogic |
| 008 | Thunno 2 t! | 230615T180538Z | The Thon |
| 052 | Zsh | 201211T012242Z | roblogic |
| 037 | ><> | 221110T095728Z | Emigna |
| 008 | Vyxal | 221109T233919Z | lyxal |
| nan | Fig | 221109T212415Z | Seggan |
| 005 | Factor + validators | 221107T132647Z | chunes |
| 050 | Julia 1.0 | 221107T095649Z | amelies |
| 026 | K ngn/k | 201208T201618Z | coltim |
| 061 | JavaScript ES6 | 160420T204129Z | edc65 |
| 172 | C clang | 210602T022005Z | Stack Ex |
| 016 | Vyxal | 210604T073009Z | emanresu |
| 011 | Vyxal | 210506T210200Z | Aaroneou |
| 147 | Pxem | 210505T083103Z | user1004 |
| 027 | x8616 machine code | 190326T160301Z | 640KB |
| 009 | Jelly | 171021T155744Z | caird co |
| 110 | C gcc | 201220T181621Z | engineer |
| 031 | GolfScript | 201220T005921Z | cnamejj |
| 061 | dc | 201211T163057Z | juh |
| 013 | Husk | 201210T233401Z | Dominic |
| 046 | R | 201210T232918Z | Dominic |
| 033 | Burlesque | 200122T153644Z | DeathInc |
| 8382 | PHP | 190326T205811Z | 640KB |
| 010 | 05AB1E | 170220T152142Z | Emigna |
| 013 | Japt | 180201T104248Z | Shaggy |
| 014 | Japt v2.0a0 | 190327T050304Z | Gymhgy |
| 074 | APLNARS | 190326T191914Z | user5898 |
| 073 | Haskell | 190310T184022Z | Laikoni |
| 011 | MathGolf | 181127T152412Z | maxb |
| 067 | Julia | 181127T094623Z | xiaodai |
| 037 | Perl 6 | 181113T084759Z | Jo King |
| 120 | Dart | 181113T081126Z | Elcan |
| 014 | Jelly | 180125T012443Z | ellie |
| 074 | Powershell | 181112T124232Z | mazzy |
| 077 | Kotlin | 180201T094837Z | jrtapsel |
| 020 | Pyt | 180125T012409Z | mudkip20 |
| 028 | K oK | 180124T233101Z | mkst |
| 020 | MATL | 170220T053855Z | B. Mehta |
| 019 | Pyth | 161025T135722Z | TheBikin |
| 041 | Perl | 160421T202345Z | Ton Hosp |
| 136 | PHP | 160421T173905Z | Flame |
| 096 | Haskell | 110131T051435Z | sepp2k |
| 042 | Retina | 160420T201136Z | Martin E |
| 035 | K4 | 140201T213037Z | Aaron Da |
| 028 | APL | 140201T225527Z | Tobia |
| 038 | APL | 140201T213505Z | Aaron Da |
| 144 | D | 110203T222936Z | Jonathan |
| 140 | GNU sed | 160111T181934Z | Toby Spe |
| 106 | JavaScript 1.8 | 130119T201019Z | kojiro |
| 097 | Haskell | 130122T170629Z | user7010 |
| 132 | Scala | 120408T040305Z | user unk |
| 063 | Q | 120407T183500Z | tmartin |
| 119 | C# | 110128T065427Z | mootinat |
| 082 | Windows PowerShell | 110213T020811Z | Joey |
| 123 | PowerShell | 110213T013403Z | Ty Auvil |
| 024 | Golfscript | 110202T165627Z | Nabb |
| 034 | Golfscript | 110201T115904Z | gnibbler |
| 085 | Ruby | 110131T080810Z | Nemo157 |
| 069 | Python | 110129T085338Z | Keith Ra |
| 044 | GolfScript | 110129T043051Z | C. K. Yo |
Vyxal 3, 10 bytes
-1 byte by lyxal
f⇄UdϾWf∑①≛
f⇄UdϾWf∑①≛
f # digits of implicit input
⇄ # reversed
U # Uninterleave
d # double the digits of 1 side of the uninterleaved (conveniently on top of stack)
Ͼ # sum each
Wf # wrap the stack and flatten the resulting array
∑ # sum the result
①≛ # is the sum divisible by 10?
💎
Created with the help of Luminespire.
<script type="vyxal3">
f⇄UdϾWf∑①≛
</script>
<script>
args=[["49927398716"],["49927398717"],["1234567812345670"],["1234567812345678"],["79927398712"],["79927398713"],["374652346956782346957823694857692364857368475368"],["374652346956782346957823694857692364857387456834"]]
</script>
<script src="https://themoonisacheese.github.io/snippeterpreter/snippet.js" type="module"/>
Tcl, 85 bytes
proc L n {expr ([regsub -all . [string rev $n] {+([incr i]%2?&:&*2%10+(&>4))}])%10<1}
proc L n {expr !(([regsub -all . [string rev $n] {+([incr i]%2?&:&*2%10+(&>4))}])%10)}
Tcl, 112 bytes
proc L n {expr 1>([lmap a [lreverse [split $n ""]] {list +([incr i]%2?$a:[join [split [expr 2*$a] ""] +])}])%10}
Python 3, 77 bytes
c=lambda a:sum(sum(divmod(int(a[-e-1])<<e%2,10))for e in range(len(a)))%10==0
PHP, 108 bytes
<?function v($s,$t=0){for($i=strlen($s);$i>=0;$i--,$c=$s[$i])$t+=$c+$i%2*(($c>4)*-4+$c%5);return!($t % 10);}
Rust, 83 81 bytes
|d|(0..).zip(d).fold(0,|a,(b,&c)|a+[(c-48)*2%10+(c-48)/5,c-48][b+d.len()&1])%10<1
- -2 bytes thanks to @ceilingcat
Go, 164 158 156 bytes
import."fmt"
func f(s string)bool{o,L:=0,len(s)
for i:=range L{r:=(s[L-i-1]-48)<<(i%2)
n,k:=Sprint(r),0
for j:=range n{k+=int(n[j])-48}
o+=k}
return o%10<1}
- -6 by @ceilingcat
- -2 from Go 1.22+ range-over-int
Explanation
import."fmt"
func f(s string)bool{
o,L:=0,len(s) // setup: sum variable, and length of string
for i:=0;i<L;i++{ // for 0 to len(s)...
r:=(s[L-i-1]-48) // get the char at i-th from the end, and convert to 0-9
<<(i%2) // if an odd index, double it
n,k:=Sprint(r),0 // convert to a string for digit summing
for j:=range n{k+=int(n[j])-48} // sum digits
o+=k} // add to total sum
return o%10<1} // check if divisible by 10
Forth (gforth), 82 bytes
: f >r i + 1- 0 r> 0 do over i - c@ '0 - i 2 mod 1+ * 10 /mod + + loop 10 mod 0= ;
Explanation
Takes input as a string, loops over the digits backwards, doubling if odd, then adds the digits of each number to the total.
Code Explanation
: f \ start new word definition
>r \ stick the string length on the return stack temporarily
i + 1- \ add the string length to the addr -1 to get the addr of the last char
0 \ initialize the sum as 0
r> 0 \ set up the loop variables to run from 0 to string length
do \ start the counted loop
over i - \ get the address of the current char
c@ '0 - \ get the value of the current char, then subtract ascii 0 to get it as a num
i 2 mod \ get whether the current index is odd or even
1+ * \ add 1 and multiply by the current digit (will be 2* if odd, and 1* if even)
10 /mod + \ get the digits of the new number and add them together
+ \ add this value to the sum
loop \ end the counted loop
10 mod 0= \ check if divisible by 10
; \ end word definition
Rust, 195 181 bytes
|s:&str|s.chars().map(|c|c.to_digit(10).unwrap()).rev().enumerate().map(|(i,n)|n<<i%2).map(|n|format!("{n}").chars().map(|c|c.to_digit(10).unwrap()).sum::<u32>()).sum::<u32>()%10<1;
I'm pretty unfamiliar with Rust golf, so feel free to suggest savings.
- -14 by @ceilingcat
Explanation
|s:&str| // input is a &str
s // original string
.chars() // get the characters
.map(|c|c.to_digit(10).unwrap()) // convert each character into a digit
.rev() // reversed
.enumerate() // into pairs of (index, digit)
.map(|(i,n)|n<<i%2) // into n or 2*n if the index is odd
.map( // getting the digit sum...
|n|format!("{n}") // to string
.chars() // get the chars chars
.map(|c|c.to_digit(10).unwrap()) // convert to digits
.sum::<u32>()) // sum them up
.sum::<u32>() // sum all the numbers up
%10<1; // check if divisible by 10
bash, 109 106 90 71 bytes
Output of 0 means True. Anything else means False.
for x in `rev<<<$1|fold -1`;{((s+=++i%2?x:(x*22/10)%10));}
echo $[s%10]
Thunno 2 t!, 8 bytes
drŻɗ⁺×ʂS
Or 10 bytes flagless:
drŻɗ⁺×ʂSt~
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
Zsh, 52 bytes
for j (${(Oas::)1})((s+=++i%2?j:j*2.2%10))
<<<$s[-1]
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.
><>, 39 37 bytes
00@:}2%1+$c%*:a%$9)++{1+$1l3=.
n;a%0=
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
Vyxal, 8 bytes
fṘ⁽dẇṠ∑t
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
Fig, \$10\log_{256}(96)\approx\$ 8.231 bytes
]SeSn2@h$f
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)
K (ngn/k), 26 bytes
{~10!+//10\(1+2!!#x)*.'|x}
Another k variant, with a major debt to @streetster's answer.
JavaScript (ES6), 61 bytes
Sum of digits of 2*n is 2*n if n in 0..4, 2*n-9 if n in 5..9. That said, all the sum can be computed in one step.
s=>!([...s].reduceRight((t,d)=>t-d-i++%2*(d>4?d-9:d),i=0)%10)
C (clang), 264 212 196 175 172 bytes
l,x;main(i){char*s;gets(s);int n[i=l=strlen(s)];for(;i--;)n[i]=s[i]-48;for(;(i+=2)<l;n[i]>9?n[i]=n[i]/10+n[i]%10:0)n[i]*=2;for(;l--;)x+=n[l];printf(x%10<1?"True":"False");}
Simply the basic way of programming the algorithm, but all whitespace is removed. All I could say is that there are a bunch of for-loops in this one.
Thanks to ceilingcat for golfing 52 bytes, another 16 bytes, and another 21 bytes, and another 3 bytes.
Vyxal, 16 bytes
₀τƛ¥₂ßd&›₀τ∑;∑₀Ḋ
₀τ # Digits...
ƛ ; # Map
¥₂ # If register is even
ßd # Double
&› # Increment register
₀τ # Digits...
∑ # Sum
∑ # Sum of all...
₀Ḋ # is divisible by 10?
Vyxal, 12 11 bytes
-1 byte thanks to @lyxal reminding me about multibyte lambdas.
ṘÞTf‡d∑ẇ∑₀Ḋ
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
Pxem, 0 bytes (content) + 147 bytes (filename).
- Filename (escaped):
.w0.-.i.c\001.+.a\001.+.t.v.m.vQJ.z.v.m.v.c.m.+.c.t.-.m.v.t.v.m.-.m\001.+.!.c\011.x\011.-XX.a.t.v.s.m.v\001.-.t.v.m.v.c0.a\046.-.v.s@.w.t.c.c.Z.m\012.%.w.d.aY.o.d.A.m.+@.a - Content is empty.
Usage
A single line that matches ^[0-9]+$, ending with EOF, is given from stdin. A single Y is output if and only if truthy.
Algorithm
- Let l1 be a list storing each digit in reverse order.
- Let s be 0.
- Let l2 be an empty list.
- If l1 is empty, go to step 9.
- Pop one value from l1 and let it be n. Push n*(s+1) onto l2.
- If last value on l2 is more than 9, subtract 9 from it.
- Let s be 1-s.
- Go to step 4.
- Calculate (sum of each item in l2)%10.
- If step 9 resulted in 0, the program returns truthy; otherwise falsey.
With comments
# 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
.a@.wXX.z
# 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
.a@.a
x86-16 machine code, 27 bytes
Binary:
00000000: bb00 0103 f1fd ac2c 30f6 df78 06d0 e0d4 .......,0..x....
00000010: 0a02 dc02 d8e2 ef93 d40a c3 ...........
Listing:
BB 0100 MOV BX, 100H ; running sum (BL) to 0, BH to a positive value
03 F1 ADD SI, CX ; start at end of input string
FD STD ; set LODSB direction to decrement
DIGIT_LOOP:
AC LODSB ; load next digit into AL, decrement SI
2C 30 SUB AL, '0' ; convert ASCII char to binary value
F6 DF NEG BH ; flip sign of BH to alternate odd/even index
78 06 JS IS_EVEN ; if not odd index, do not double
D0 E0 SHL AL, 1 ; double the value
D4 0A AAM ; split digits (ex: 18 --> AH = 1, AL = 8)
02 DC ADD BL, AH ; add tens digit to running sum
IS_EVEN:
02 D8 ADD BL, AL ; add ones digit to running sum
E2 EF LOOP DIGIT_LOOP
93 XCHG AX, BX ; sum is in BL, move to AL for mod 10 check
D4 0A AAM ; ZF = ( AL % 10 == 0 )
C3 RET ; return to caller
Uses (abuses) x86's BCD-to-binary instruction AAM to handle the individual digit splitting and modulo 10 check.
Callable function, input card num string pointer in SI, length in CX. Output: ZF if valid.
Example test program output:
Alternate version, 29 bytes
33 DB XOR BX, BX ; running sum (BL) to 0
03 F1 ADD SI, CX ; start at end of string
4E DEC SI ; align for WORD
FD STD ; set LODSB direction to decrement
DIGIT_LOOP:
AD LODSW ; load next two digits into AH:AL, dec SI by 2
25 0F0F AND AX, 0F0FH ; convert ASCII chars to binary value
02 DC ADD BL, AH ; add ones digit of even index to sum
49 DEC CX ; decrement counter for WORD
74 0A JZ DONE ; if input is odd length, will be 0 at the end
D0 E0 SHL AL, 1 ; double the value
D4 0A AAM ; split digits (ex: 18 --> AH = 1, AL = 8)
02 DC ADD BL, AH ; add tens digit to sum
02 D8 ADD BL, AL ; add ones digit to sum
E2 ED LOOP DIGIT_LOOP
DONE:
93 XCHG AX, BX ; move sum to AL for mod 10 check
D4 0A AAM ; ZF = ( AL % 10 == 0 )
C3 RET ; return to caller
This version loads two digits at the same time, eliminating the flip/flop branch. The issue here is having to check for an odd number of digits on the input and discard the value in memory right before the beginning of the string once it reaches the last word. Obviously not shorter, but perhaps someone clever can golf it more!
Jelly, 12 11 9 bytes
ṚḤÐeDFS⁵ḍ
How it works
ṚḤÐeDFS⁵ḍ - Main link. Takes an integer n on the left
Ṛ - Cast n to digits and reverse
Ðe - To values at even indices:
Ḥ - Unhalve; Double
D - Cast to digits
F - Flatten
S - Sum
ḍ - Divisible by:
⁵ - 10?
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
}
GolfScript, 31 bytes
.,2%0\@{48-..4>+@!:a*++a}/;10%!
Golfscript pushes the input as a list of characters to the stack at the start of the program.
. Duplicate the top of the stack (input)
,2% Compute the modulo 2 of the length of the input,
pushed 1/0 on the stack if the number if odd/even
0 Push an accumulater var on the stack, set to 0
\ Flip the even/odd and accumulator order on the stack
@ Bring the 3rd entry forward, input to the top
{ } Code block...
/ Apply the block of code to the elements of the list at
the top of the stack. Each time through the loop, the
next element from the list if pushed to the top of the
stack
48- Subtract "0" from the top of stack (which is a codepoint
for the current digit/character)
.. Duplicate the top of stack (the current digit) twice
4>+ If the current digit is >4 add one to the digit
@ Pull the 3rd entry, the even/odd indicator, to the top
!:a Flip the value and save in variable "a"
* Multiple the top two stack entries, will be "0" or the
value of current digit, with or without "1" more for the
"+10" rule
++ Add the current digit, to the possible "double" and
"even/odd" bump
a Push the flipped even/odd indicated to the top
; Drop the stop of stack, the even/odd indicator
10% Find the modulo 10 of the accumulated digits
! Invert the result
The only thing on the stack is the answer, which is printed by default
dc, 61 bytes
[A~rdZ1<S]dsSxz2%1=0[2*SaSaz1<LLaLalSx]dsLx[+z1<L]dsLxA%0=0zp
[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:
- Each register holds 0 by default
- Comparisons attempt to execute whatever's in the specified register (
0here) - 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.
Husk, 15 13 bytes
Edit: -2 bytes thanks to Razetime
¬→dṁΣzod*¢ḣ2↔
¬ # 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
Burlesque, 33 bytes
riXX<-J2ENj2en2?***{XX++}ms10.%z?
ri # Read input as int
XX # Explode into digits
<- # Reverse
J2EN # Duplicate and take every 2nd starting from 1
j2en # Take the other half
2?* # Multiply each digit by 2
** # Remerge arrays
{XX++}ms # Sum the digits of multidigit and then sum result
10.%z? # If result `mod` 10 is 0
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
05AB1E, 12 10 bytes
RSāÈ>*SOTÖ
Try it online! or as a Test Suite
Explanation
R # reverse input
S # split to list of digits
ā # push range[1 ... len(input)]
È # map isEven on each
> # increment
* # multiply doubling every other item
SO # sum digits
TÖ # mod 10 == 0
Japt, 14 13 bytes
Takes input as an array of digits.
ÔxÈ*ÒYu)ìxÃvA
ÔxÈ*ÒYu)ìxÃvA :Implicit input of array
Ô :Reverse
x :Reduce by addition
È :After passing each element at 0-based index Y through the following function
* : Multiply by
Ò : Bitwise increment
Yu : Y modulo 2
) : End multiplication
ì : Convert to digit array
x : Reduce by addition
à :End function
v :Test for divisibility by
A : 10
Japt v2.0a0, 14 bytes
¬ÔxÈ*ÒYu)ìxÃvA
The first byte can be removed if I took input as array of chars.
¬ //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
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)
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
MathGolf, 11 bytes
▒xôï¥)*Σ+♂÷
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
Julia, 67 bytes
x=digits(n)
sum(x[1:2:end])+sum(reduce(vcat,digits.(x[2:2:end]*2)))
Perl 6, 37 bytes
(*.flip.comb >>*>>[1,2]).comb.sum%%10
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
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;
Jelly, 14 bytes
DUḤJḤ$¦DS$€S⁵ḍ
Explanation:
D get digits
U reverse array
JḤ$ for every other index,
Ḥ ¦ double the value
€ for each value,
D $ get the digits
S$ and sum them
S sum the list
⁵ḍ check if it's divisible by 10
Powershell, 74 bytes
param($s)$s[$s.Length..0]|%{(1+$i++%2)*"$_"}|%{$r+=$_-9*($_-gt9)}
!($r%10)
Explanation
- for each char of an argument string, in reverse order
- get a digit of double value of a digit
- a double value of a digit can not be greater then 18. Therefore, we accumulate a value minus 9 if value > 9
- return true if the remainder of the division by 10 is 0
Test script
$f = {
param($s)$s[$s.Length..0]|%{(1+$i++%2)*"$_"}|%{$r+=$_-9*($_-gt9)}
!($r%10)
}
@(
,("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)
) | % {
$s, $expected = $_
$result = &$f $s
"$($result-eq$expected): $result : $s"
}
Output
True: True : 49927398716
True: False : 49927398717
True: True : 1234567812345670
True: False : 1234567812345678
True: False : 79927398710
True: False : 79927398711
True: False : 79927398712
True: True : 79927398713
True: False : 79927398714
True: False : 79927398715
True: False : 79927398716
True: False : 79927398717
True: False : 79927398718
True: False : 79927398719
True: True : 374652346956782346957823694857692364857368475368
True: False : 374652346956782346957823694857692364857387456834
True: False : 8
True: True : 0
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
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)
K (oK), 28 bytes
Solution:
~10!+/48!,/$(1+2!!#x)*48!|x:
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:
MATL, 23 20 bytes (non competing)
P!Utn:2X\!*t9>+s10\~
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
s % add them
10 % number literal
\ % mod 10
~ % logical 'not' (element-wise)
% (implicit) convert to string and display
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.
Try it online or verify all test cases
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
Perl, 46 42 41 bytes
Includes +1 for -p
Give input on STDIN:
luhn.pl <<< 79927398713
luhn.pl:
#!/usr/bin/perl -p
s%.%$=-=-$&-$&*1.2*/\G(..)+$/%eg;$_=/0$/
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);}
Haskell, 96 bytes
There must be a better/shorter way, but here's my Haskell solution in 96 characters:
l=(==0).(`mod`10).sum.zipWith($)(cycle[id,\x->x`mod`5*2+x`div`5]).reverse.map((+(-48)).fromEnum)
Sadly the digitToInt function can only be used if you import Data.Char first. Otherwise I could get down to 88 characters by replacing ((+(-48)).fromEnum) with digitToInt.
Retina, 43 42 bytes
Retina is (much) newer than this challenge.
;
r`(.);.
$1$&
\d
$*
1+
$.&
.
$*
$
$._
0$
The leading empty line is significant.
Prints 0 for falsy and 1 for truthy results.
Try it online! (Slightly modified to run all test cases at once.)
Explanation
;
Insert ; in every position to separate digits.
r`(.);.
$1$&
From the right, we repeatedly match two digits and double the left one. This way we avoid an expensive reversing of the list.
\d
$*
We match each digit and convert it to that many 1s (that is, we convert each digit to unary).
1+
$.&
This matches each unary number and converts it back to decimal by replacing it with its length. Together with the previous stage, this adds the doubled digits.
.
$*
Again, we match every character and turn it into that many 1s. That is we convert each digit individually back to unary. This also matches the ; separators, which are treated as zeros in the conversion, which means they're simply removed. Since all the unary numbers are now squashed together we've automatically added the unary representations of the all digits together.
$
$._
At the end, we insert the length of the entire string, i.e. the decimal representation of the unary checksum.
0$
Finally we count the number of matches of this regex, i.e. we check whether the decimal representation ends in 0, printing 0 or 1 accordingly.
K4, 35 bytes
{~.*|$+/.:',/$x*1+1{y;~x}\|x:|.:'x}
APL, 28 bytes
{0=10|+/⍎¨∊⍕¨v×⌽2-2|⍳⍴v←⍎¨⍵}
Exploded view
{ v←⍎¨⍵} ⍝ turn the string into a numeric vector of its digits, v
2-2|⍳⍴v ⍝ make a vector of the same length, with 2 in every 2nd place
v×⌽ ⍝ multiply it with v, starting from the right
∊⍕¨ ⍝ turn each component into a string and collect all the digits
+/⍎¨ ⍝ turn each digit again into a number and sum them
0=10| ⍝ check whether the sum is a multiple of 10
Examples
{0=10|+/⍎¨∊⍕¨v×⌽2-2|⍳⍴v←⍎¨⍵} '79927398713'
1
{0=10|+/⍎¨∊⍕¨v×⌽2-2|⍳⍴v←⍎¨⍵} '123456789'
0
APL, 38 bytes
d←10∘⊥⍣¯1⋄{0=10|+/+/d x×1+~2|⍳⍴x←⌽d ⍵}
expects the number as a number, not a string, but that's only because tryAPL (understandably) doesn't implement ⍎
further reducible, i'm sure…
D, 144 bytes
bool f(S)(S s){int t(C)(C c){return to!int(c)-'0';}int n,v;foreach(i,c;array(retro(s))){v=i&1?t(c)*2:t(c);n+=v>=10?v%10+v/10:v;}return n%10==0;}
More legibly:
bool f(S)(S s)
{
int t(C)(C c)
{
return to!int(c) - '0';
}
int n, v;
foreach(i, c; array(retro(s)))
{
v = i & 1 ? t(c) * 2 : t(c);
n += v >= 10 ? v % 10 + v / 10 : v;
}
return n % 10 == 0;
}
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
# zero-pad to even length
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/
JavaScript 1.8: 106 characters
This is an original solution I came up with before I found this post:
function(n){return!(n.split('').reverse().reduce(function(p,c,i){return(+c&&((c*(1+i%2)%9)||9))+p},0)%10)}
Readable form:
function luhnCheck(ccNum) {
return !( // True if the result is zero.
ccNum.split('').
reverse(). // Iterate over the string from rtl.
reduce(function(prev, cur, idx) {
return prev + // Sum the results of each character.
(+cur && // If the current digit is 0, move on.
((cur * (1 + idx % 2) // Double cur at even indices.
% 9) || 9)); // Sum the digits of the result.
}, 0)
% 10); // Is the sum evenly divisible by 10?
}
Haskell: 97
For some reason this isn't working for me, so here is my version
l=(\x->(==0)$(`mod`10).sum$zipWith($)(cycle[id,sum.map(read.(:"")).show.(*2)])(map(read.(:""))x))
Scala: 132
def q(x:Int)=x%10+x/10
def c(i:String)={val s=i.reverse
(s(0)-48)==10-(s.tail.sliding(2,2).map(n=>(q((n(0)-48)*2)+n(1)-48)).sum%10)}
invocation:
c("79927398713")
- reverse ("79927398713") = 31789372997
- s(0), s.tail: (3)(1789372997)
- sliding (2,2) = (17 89 37 29 97)
- map (q((n(0)-48*2 + n(1)-48)) => q(('1'-'0')*2)+ '7'-'0')=1*2+7
Q, 63
{0=mod[(+/)"I"$(,/)($)($)@["I"$'x;1+2*'(!)(_)((#)x)%2;*;2];10]}
usage
q){0=mod[(+/)"I"$(,/)($)($)@["I"$'x;1+2*'(!)(_)((#)x)%2;*;2];10]}"79927398711"
0b
q){0=mod[(+/)"I"$(,/)($)($)@["I"$'x;1+2*'(!)(_)((#)x)%2;*;2];10]}"79927398712"
0b
q){0=mod[(+/)"I"$(,/)($)($)@["I"$'x;1+2*'(!)(_)((#)x)%2;*;2];10]}"79927398713"
1b
C# 119 characters:
bool l(string n){return(String.Join("",n.Reverse().Select((x,i)=>(x-48)*(i%2<1?1:2)+"").ToArray()).Sum(x=>x-48))%10<1;}
Not too bad for a code golf n00b in a statically typed language, I hope.
This can be reduced to 100:
bool l(string n){return String.Join("",n.Reverse().Select((x,i)=>(x-48)*(i%2+1))).Sum(x=>x+2)%10<1;}
Windows PowerShell, 82
filter f{!((''+($_[($_.length)..0]|%{+"$_"*($i++%2+1)})-replace'.','+$&'|iex)%10)}
History:
- 2011-02-13 03:08 (84) First attempt.
- 2011-02-13 12:13 (82) I don't need to join, as spaces do not hurt.
+1 + +3can still be evaluated.
PowerShell 123
filter L($x){$l=$x.Length-1;$l..0|%{$d=$x[$_]-48;if($_%2-eq$l%2){$s+=$d}elseif($d-le4){$s+=$d*2}else{$s+=$d*2-9}};!($s%10)}
Golfscript - 24 chars
-1%{2+0!:0)*109%+}*10%8=
Explanation:
-1%reverses the string{begins a block (which we use as a loop). Each character in the strings is pushed as it's ascii value.2+adds 2. (the ascii value of a digit is 48+n, so we have 50+n now and the last digit is n)0!:0inverts the value of 0 and stores it (everything is a variable), so we have 1 on the first iteration, 0 on the second, etc.)*adds one to this value and multiplies it, so we multiply by 2, then 1, then 2, etc.109%is remainder modulo 109. This affects only values 5-9 which have been doubled and reduces them to the correct value.+adds this value to the running sum
}*ends the block and does a 'fold' operation. First, the first character is pushed (since we have reversed, this is the check digit). Then, alternate pushing and executing the block. Thus, we are using the first character's ascii value as the starting value for the running sum.10%takes the remainder modulo 10.8=will return 1 if the value is 8. We use this because we did not normalize the first pushed character (the check digit).
One might think that we could use 8- instead of 2+ to save a character by changing 109% to 89%, except then we would need to add a space so the - is subtraction (instead of -0).
Golfscript - 34 chars
{15&}%.-2%\);-2%{.+(9%)}%+{+}*10%!
Example number from wikipedia page 4992739871
{15&}% does a bitwise and of each ascii digit with 00001111
now I have a list of digits
[4 9 9 2 7 3 9 8 7 1 6]
. makes a copy of the list, now I have two identical lists
[4 9 9 2 7 3 9 8 7 1 6] [4 9 9 2 7 3 9 8 7 1 6]
-2% like [::-2] in python takes every second element in reverse
[4 9 9 2 7 3 9 8 7 1 6] [6 7 9 7 9 4]
\ swap the two lists around
[6 7 9 7 9 4] [4 9 9 2 7 3 9 8 7 1 6]
); drop the last digit off the list
[6 7 9 7 9 4] [4 9 9 2 7 3 9 8 7 1]
-2% same as before
[6 7 9 7 9 4] [1 8 3 2 9]
{ for each item in the list ...
.+ ... double it ...
( ... subtract 1 ...
9% ... mod 9 ...
)}% ... add 1 ...
[6 7 9 7 9 4] [2 7 6 4 9]
+ join the two lists
[6 7 9 7 9 4 2 7 6 4 9]
{+}* add the elements up
70
10% mod 10
0
! invert the result
1
Ruby - 85 characters
def f s
l=s.size
s.chars.map{|k|(i=k.to_i*((l-=1)%2+1))%10+i/10}.inject(:+)%10==0
end
Python, 73 69 characters
def P(x):D=map(int,x);return sum(D+[d-d/5*9for d in D[-2::-2]])%10==0
GolfScript, 44 chars
-1%{16%}%2/1,\+{(\.{0=2*.9>9*-+}{;}if+}*10%!
Selected commentary
Interestingly, the first two items below demonstrate three completely different uses of the % operator: array selection, map, and mod. Most GolfScript operators are "context-sensitive", giving them hugely divergent behaviours depending on what types the arguments are.
-1%reverses the string. This is important as the digit pairs are counted from the right.{16%}%converts all the ASCII digits into numbers, by modding them with 16.2/splits the array into groups of 2.1,is a cheap way to do[0].\+effectively prepends the 0 to the digits array. It does this by swapping then concatenating.
The 0 is prepended in preparation for the fold that comes in next. Rather than taking an explicit initial value, GolfScript's fold uses the first item in the array as the initial value.
Now, let's look at the actual fold function. This function takes two arguments: the folded value, and the current item on the array (which in this case will be an array of 2 or (uncommonly) 1, because of the 2/ earlier). Let's assume the arguments are 1 [2 3].
(\.splits out the leftmost array element, moves the remaining array to the front, then copies it. Stack now looks like:1 2 [3] [3].- The
ifchecks if the array is empty (which is the case for the last group when dealing with an odd-sized account number). If so, then no special processing happens (just pop off the empty array). - For an even group:
0=grabs the first (only, in this case) element of the array.1 2 32*doubles the number.1 2 6.9>9*-subtracts 9 from the number if it's greater than 9. Implemented as: copy the number, compare with 9, multiply the result (which is either 0 or 1) with 9, then subtract.1 2 6+finally adds that to the first number.1 8
+(after theif) adds the result of theifto the original value, resulting in the new folded value.
After the folding completes, we simply mod with 10 (10%), and negate the result (!), so that we return 1 iff the sum is a multiple of 10.
