62
\$\begingroup\$

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.

Leaderboard

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>

\$\endgroup\$
0

64 Answers 64

2
\$\begingroup\$

Julia 1.0, 51 50 bytes

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

Try it online!

\$\endgroup\$
1
\$\begingroup\$

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))
\$\endgroup\$
1
\$\begingroup\$

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/
\$\endgroup\$
1
\$\begingroup\$

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…

\$\endgroup\$
1
\$\begingroup\$

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);}
\$\endgroup\$
1
\$\begingroup\$

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
s       % add them
10      % number literal
\       % mod 10
~       % logical 'not' (element-wise)
        % (implicit) convert to string and display
\$\endgroup\$
0
1
\$\begingroup\$

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:
\$\endgroup\$
1
\$\begingroup\$

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
        S$     and sum them
           S   sum the list
            ⁵ḍ check if it's divisible by 10
\$\endgroup\$
3
  • \$\begingroup\$ Why is this non-competing? \$\endgroup\$
    – mudkip201
    Jan 25, 2018 at 1:32
  • \$\begingroup\$ @mudkip201 Correct me if I'm wrong, but this version of Jelly didn't exist when the question was asked, so it isn't valid for the question. \$\endgroup\$
    – ellie
    Jan 25, 2018 at 1:41
  • 3
    \$\begingroup\$ Pretty sure there was a meta consensus that said that languages that were made after the challenge aren't 'non-competing' any more \$\endgroup\$
    – mudkip201
    Jan 25, 2018 at 1:43
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
  • \$\begingroup\$ 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. \$\endgroup\$
    – Shaggy
    Mar 28, 2019 at 17:23
1
\$\begingroup\$

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

\$\endgroup\$
1
\$\begingroup\$

R, 46 bytes

function(x,y=rev(x)*1:2)!sum(y%%10+y%/%10)%%10

Try it online!

\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
2
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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
}
\$\endgroup\$
1
  • \$\begingroup\$ Suggest e<<=c++%2 instead of e*=c++%2+1 \$\endgroup\$
    – ceilingcat
    Dec 25, 2020 at 2:33
1
\$\begingroup\$

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\[email protected]\012.%[email protected]
  • Content is empty.

Try it online!

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

  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.

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
[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]
\$\endgroup\$
1
\$\begingroup\$

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?
\$\endgroup\$
1
\$\begingroup\$

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)
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

><>, 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
\$\endgroup\$
1
\$\begingroup\$

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

\$\endgroup\$
1
\$\begingroup\$

Thunno 2 t!, 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
\$\endgroup\$
0
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

Tcl, 85 bytes

proc L n {expr ([regsub -all . [string rev $n] {+([incr i]%2?&:&*2%10+(&>4))}])%10<1}

Try it online!

Tcl, 86 bytes

proc L n {expr !(([regsub -all . [string rev $n] {+([incr i]%2?&:&*2%10+(&>4))}])%10)}

Try it online!

Tcl, 119 bytes

proc L n {expr !(([join [lmap a [lreverse [split $n ""]] {expr [incr i]%2?$a:[join [split [expr 2*$a] ""] +]}] +])%10)}

Try it online!

\$\endgroup\$
0
0
\$\begingroup\$

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!

\$\endgroup\$
0
\$\begingroup\$

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

\$\endgroup\$
0
\$\begingroup\$

Julia, 67 bytes

x=digits(n)
sum(x[1:2:end])+sum(reduce(vcat,digits.(x[2:2:end]*2)))
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.