Thuật toán Luhn để xác minh số thẻ tín dụng, v.v.


49

Thử thách

Viết chương trình hoặc hàm ngắn nhất để tính toán Thuật toán Luhn để xác minh số (thẻ tín dụng).

Thuật toán Luhn giải thích

Từ RosettaCode , thuật toán này cho các mục đích của thử thách này được chỉ định như vậy, với đầu vào ví dụ là 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

Quy tắc IO

Đầu vào : Chuỗi hoặc số (lựa chọn của bạn), ở định dạng lựa chọn đầu vào / đầu ra của ngôn ngữ của bạn

Đầu ra : Giá trị trung thực hoặc sai , tương ứng, cho biết liệu đầu vào có hợp lệ theo thử nghiệm ở trên hay không.

Ghi chú / Mẹo

  • Cố gắng không vô tình đăng số thẻ tín dụng hoặc số tài khoản của riêng bạn, nếu bạn sử dụng chúng để kiểm tra :)

  • Nếu đầu vào không hợp lệ và không thể xử lý với thuật toán được chỉ định (nghĩa là quá ngắn để làm việc), bạn có thể làm bất cứ điều gì bạn muốn, bao gồm cả làm nổ máy tính của tôi.

  • Tuy nhiên , dấu đầu dòng không có nghĩa là ngôn ngữ của bạn có thể làm bất cứ điều gì nó muốn với Số quá lớn để có thể xử lý. Nếu ngôn ngữ của bạn không có khả năng xử lý trường hợp kiểm tra, thì hãy xem xét lấy một chuỗi làm đầu vào.

Ví dụ

Các ví dụ sau đã được xác thực với tập lệnh Python này ; nếu bạn nghĩ ai đó sai hoặc có câu hỏi, chỉ cần 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  **

** theo cách triển khai Python, nhưng bạn có thể làm bất cứ điều gì vì chúng quá ngắn để đủ điều kiện tuân thủ nghiêm ngặt các đặc điểm kỹ thuật.


Nếu bất kỳ câu trả lời nào ở trên làm mất hiệu lực các câu trả lời hiện có (mặc dù tôi tin rằng điều đó là không thể), thì những câu trả lời đó vẫn còn hiệu lực. Tuy nhiên, câu trả lời mới , để có giá trị, nên tuân theo các đặc điểm kỹ thuật ở trên.

Bảng xếp hạng

Câu trả lời:


21

Golfscript - 24 ký tự

-1%{2+0!:0)*109%+}*10%8=

Giải trình:

  1. -1% đảo ngược chuỗi
  2. {bắt đầu một khối (mà chúng ta sử dụng như một vòng lặp). Mỗi ký tự trong chuỗi được đẩy theo giá trị ascii.
    1. 2+ thêm 2. (giá trị ascii của một chữ số là 48 + n, vì vậy chúng ta có 50 + n và chữ số cuối cùng là n)
    2. 0!:0 đảo ngược giá trị 0 và lưu trữ nó (mọi thứ đều là biến), vì vậy chúng ta có 1 trên lần lặp đầu tiên, 0 trên lần thứ hai, v.v.
    3. )* thêm một vào giá trị này và nhân nó, vì vậy chúng tôi nhân với 2, rồi 1, rồi 2, v.v.
    4. 109% là phần còn lại modulo 109. Điều này chỉ ảnh hưởng đến các giá trị 5-9 đã được nhân đôi và giảm chúng về giá trị chính xác.
    5. + thêm giá trị này vào tổng số đang chạy
  3. }*kết thúc khối và thực hiện thao tác 'gấp'. Đầu tiên, ký tự đầu tiên được đẩy (vì chúng ta đã đảo ngược, đây là chữ số kiểm tra). Sau đó, luân phiên đẩy và thực hiện khối. Do đó, chúng tôi đang sử dụng giá trị ascii của ký tự đầu tiên làm giá trị bắt đầu cho tổng số đang chạy.
  4. 10% lấy modulo còn lại 10.
  5. 8= sẽ trả về 1 nếu giá trị là 8. Chúng tôi sử dụng giá trị này vì chúng tôi không bình thường hóa ký tự đẩy đầu tiên (chữ số kiểm tra).

Người ta có thể nghĩ rằng chúng ta có thể sử dụng 8-thay vì 2+lưu một ký tự bằng cách thay đổi 109%thành 89%, ngoại trừ sau đó chúng ta sẽ cần thêm một khoảng trắng để -trừ đi (thay vì -0).


11

GolfScript, 44 ký tự

-1%{16%}%2/1,\+{(\.{0=2*.9>9*-+}{;}if+}*10%!

Bình luận được chọn

Thật thú vị, hai mục đầu tiên bên dưới thể hiện ba cách sử dụng hoàn toàn khác nhau của %toán tử: chọn mảng, bản đồ và mod. Hầu hết các toán tử GolfScript đều "nhạy cảm theo ngữ cảnh", tạo cho chúng các hành vi cực kỳ khác nhau tùy thuộc vào loại đối số.

  1. -1%đảo ngược chuỗi. Điều này rất quan trọng vì các cặp chữ số được tính từ bên phải.
  2. {16%}% chuyển đổi tất cả các chữ số ASCII thành số, bằng cách sửa đổi chúng bằng 16.
  3. 2/ chia mảng thành các nhóm 2.
  4. 1,là một cách rẻ tiền để làm [0].
  5. \+hiệu quả chuẩn bị 0 cho mảng chữ số. Nó thực hiện điều này bằng cách hoán đổi sau đó ghép nối.

Số 0 được chuẩn bị trước để chuẩn bị cho lần gấp tiếp theo. Thay vì lấy một giá trị ban đầu rõ ràng, nếp gấp của GolfScript sử dụng mục đầu tiên trong mảng làm giá trị ban đầu.

Bây giờ, hãy nhìn vào chức năng gấp thực tế. Hàm này có hai đối số: giá trị gấp và mục hiện tại trên mảng (trong trường hợp này sẽ là một mảng 2 hoặc (không phổ biến) 1, vì 2/trước đó). Hãy giả sử các đối số là 1 [2 3].

  1. (\.tách ra phần tử mảng ngoài cùng bên trái, di chuyển mảng còn lại ra phía trước, sau đó sao chép nó. Stack bây giờ trông như : 1 2 [3] [3].
  2. Các ifkiểm tra xem mảng rỗng (đó là trường hợp đối với nhóm cuối cùng khi giao dịch với một số tài khoản lẻ cỡ). Nếu vậy, thì không có xử lý đặc biệt nào xảy ra (chỉ bật ra khỏi mảng trống).
  3. Đối với một nhóm chẵn:
    1. 0= lấy phần tử đầu tiên (duy nhất, trong trường hợp này) của mảng. 1 2 3
    2. 2* nhân đôi số lượng. 1 2 6
    3. .9>9*- trừ 9 từ số nếu lớn hơn 9. Thực hiện như: sao chép số, so sánh với 9, nhân kết quả (bằng 0 hoặc 1) với 9, sau đó trừ đi. 1 2 6
    4. + cuối cùng thêm vào số đầu tiên. 1 8
  4. +(sau khi if) thêm kết quả của ifgiá trị ban đầu, dẫn đến giá trị gấp mới.

Sau khi hoàn thành việc gấp, chúng ta chỉ cần sửa đổi với 10 ( 10%) và phủ định kết quả ( !), để chúng ta trả về 1 nếu tổng số là bội số của 10.


Điều này dường như trả về 0 cho số ví dụ trên wikipedia (
49927398716

bước sóng. Tôi đã quên sử dụngecho -n
gnibbler

1
@gnibbler: Haha, thất bại. :-P (Nghiêm túc mà nói, tôi cũng bị ném đá bởi điều đó, trong thử nghiệm ban đầu của tôi.)
Chris Jester-Young

1
Một vài nơi để lưu một vài nhân vật dễ dàng ở đây. -1% 2/có thể kết hợp thành -2/. 1,có thể được thay thế bằng 0(0 bị ép buộc vào một mảng, sau đó +được nối). 9>9*-có thể được thay thế bằng 9>+(vì chúng tôi chỉ quan tâm đến chữ số cuối cùng). Ngoài ra, việc kiểm tra độ dài lẻ hơi dài, sử dụng .,2%,\+ngắn hơn. Sau khi làm điều này, chúng ta cũng có thể thay đổi {16%}%(\0=vào {16}/(bên trong vòng lặp). Khi bạn đã thực hiện tất cả điều đó, nó sẽ trông giống như thế này : .,2%,\+-2/0\+{{16%}/2*.9>+++}*10%!.
Nabb

@Nabb: Cảm ơn! Tôi sẽ kết hợp những thứ đó vào giải pháp của tôi, mặc dù có vẻ như bạn đã có một cú đá nghiêm túc. :-)
Chris Jester-Young

11

Con trăn, 73 69 ký tự

def P(x):D=map(int,x);return sum(D+[d-d/5*9for d in D[-2::-2]])%10==0

4
Bạn có thể lưu thêm hai ký tự bằng cách không lặp lại: D[-2::-2]-> D[1::2]vì thứ tự của một khoản tiền không quan trọng :)
ThinkChaos

==0có thể rút ngắn thành<1
Black Owl Kai

10

Python 3, 77 byte

c=lambda a:sum(sum(divmod(int(a[-e-1])<<e%2,10))for e in range(len(a)))%10==0

9

C # 119 ký tự:

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;}

Không quá tệ cho một mã golf n00b trong một ngôn ngữ gõ tĩnh, tôi hy vọng.

Điều này có thể giảm xuống 100 :

bool l(string n){return String.Join("",n.Reverse().Select((x,i)=>(x-48)*(i%2+1))).Sum(x=>x+2)%10<1;}

Đó là một ý tưởng tốt và một cách tiếp cận thú vị, nhưng nó dường như không hoạt động. Ít nhất là không với vài bài kiểm tra của tôi. Có vẻ như chữ "i" trong lambda đầu tiên của bạn được coi là chỉ số của ký tự trong chuỗi. Nó có hoạt động như bình thường không? Nếu vậy, tại sao bạn chỉ đảo ngược chuỗi chỉ để sau đó sửa đổi nó dựa trên vị trí chỉ mục? Có vẻ hơi dư thừa, không?
Nellius

Tôi chỉ kiểm tra một trong các thẻ tín dụng của mình và một vài lỗi do TBH. (Sử dụng trình gỡ lỗi VS 2008) Thuật toán được cho là tăng gấp đôi mỗi chữ số thứ hai bắt đầu bằng chữ số LAST. Nếu tôi không đảo ngược chuỗi, nó sẽ không chính xác cho các chuỗi có độ dài lẻ.
mootinator

Hóa ra tôi đã có kết quả i%2<1?1:2ngược. Cảm ơn.
mootinator

8

Golfscript - 34 ký tự

{15&}%.-2%\);-2%{.+(9%)}%+{+}*10%!

Số ví dụ từ trang wikipedia 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

Điều .+(9%)này rất sáng tạo (đối với tôi, dù sao). Tôi thích! +1
Chris Jester-Young

Mặc dù vậy, GolfScript cần một toán tử phân vùng, do đó bạn không cần phải thực hiện việc này "bỏ mục kết thúc và lặp lại" vô nghĩa. :-)
Chris Jester-Young

1
@Chris, tôi đã biết về điều đó nhiều năm trước được gọi là "bỏ đi số tiền phạt". Đây là một cách gọn gàng để kiểm tra
kỹ lưỡng các

3
Điều này sẽ không hoạt động với giá trị 0 được nhân đôi ( 0(9%)là 9 chứ không phải 0).
Nabb

8

PHP, 108 byte

<?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);}

7

Ruby - 85 ký tự

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

Bạn có thể biết về điều này, nhưng bạn có thể làm .sum thay vì .inject (: +) để lưu 7 byte
Håvard Nygård

7

Haskell, 96 byte

Phải có cách tốt hơn / ngắn hơn, nhưng đây là giải pháp Haskell của tôi với 96 ký tự :

l=(==0).(`mod`10).sum.zipWith($)(cycle[id,\x->x`mod`5*2+x`div`5]).reverse.map((+(-48)).fromEnum)

Đáng buồn là digitToIntchức năng chỉ có thể được sử dụng nếu bạn import Data.Charđầu tiên. Nếu không, tôi có thể giảm xuống 88 ký tự bằng cách thay thế ((+(-48)).fromEnum)bằng digitToInt.


6

Windows PowerShell, 82

filter f{!((''+($_[($_.length)..0]|%{+"$_"*($i++%2+1)})-replace'.','+$&'|iex)%10)}

Lịch sử:

  • 2011/02/13 03:08 (84) Lần thử đầu tiên.
  • 2011/02/13 12:13 (82) Tôi không cần tham gia, vì không gian không bị tổn thương. +1 + +3vẫn có thể được đánh giá.

5

Q, 63

{0=mod[(+/)"I"$(,/)($)($)@["I"$'x;1+2*'(!)(_)((#)x)%2;*;2];10]}

sử dụng

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

47 byte với {0=mod[sum"J"$raze($)($)x*#:[x]#1 2]10}"I"$'(|)một cách khác nhau để nhân đôi các chỉ số lẻ.
streetster

5

D, 144 byte

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;}

Dễ đọc hơn:

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;
}

5

APL, 28 byte

{0=10|+/⍎¨∊⍕¨v×⌽2-2|⍳⍴v←⍎¨⍵}

Khung nhìn bùng nổ

{                     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

Ví dụ

      {0=10|+/⍎¨∊⍕¨v×⌽2-2|⍳⍴v←⍎¨⍵} '79927398713'
1
      {0=10|+/⍎¨∊⍕¨v×⌽2-2|⍳⍴v←⍎¨⍵} '123456789'
0

1
-2:{0=10|+/⍎¨∊⍕¨⍵×⌽2-2|⍳⍴⍵}⍎¨
Adám

4

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)}

4

Perl, 46 42 41 byte

Bao gồm +1 cho -p

Cung cấp đầu vào trên STDIN:

luhn.pl <<< 79927398713

luhn.pl:

#!/usr/bin/perl -p
s%.%$=-=-$&-$&*1.2*/\G(..)+$/%eg;$_=/0$/

Bạn có thể vui lòng giải thích làm thế nào điều này hoạt động? Bạn dường như đang giảm dần theo trận đấu và sau đó là trận đấu lần 1,2 nhưng chỉ ở đúng vị trí. Tại sao 1,2? Có nên không $=-=-$&-$&*/\G(..)+$/?
msh210

3
@ msh210: Nó mã hóa hiệu ứng của phép nhân với 2. 0..4* 2 cho 0, 2, 4, 6, 8nhưng 5..9đưa ra 10,12,14,16,18tổng 1 3 5 7 9nào có cùng các chữ số cuối cùng 11 13 15 17 19có cùng giá trị như 0..9 * 2.2khi bạn cắt ngắn thành số nguyên. Đầu tiên $&đã đóng góp một yếu tố 1, do đó 1.2vẫn cần phải điều chỉnh . $=chỉ có thể giữ các số nguyên và bắt đầu bằng một giá trị kết thúc bằng 0, vì vậy hãy quan tâm đến việc cắt bớt. Các giá trị âm là cần thiết vì /\G/regex thay đổi bất kỳ số $&tĩnh nào trên ngăn xếp đánh giá, do đó chúng cần được thay đổi
TonMedel

Oh. Xuất sắc! Và cảm ơn đã giải thích.
msh210

3

JavaScript (ES6), 61 byte

Không cạnh tranh, vì JavaScript rất khác trong năm 2011.

Tổng các chữ số 2*n2*nnếu n in 0..4, 2*n-9nếu n in 5..9. Điều đó nói rằng, tất cả số tiền có thể được tính trong một bước.

s=>!([...s].reduceRight((t,d)=>t-d-i++%2*(d>4?d-9:d),i=0)%10)

3

Thạch , 12 11 byte

ṚḤJḤ$¦DFS⁵ḍ

Hãy thử trực tuyến! (với tất cả các trường hợp thử nghiệm)

Làm thế nào nó hoạt động

ṚḤJḤ$¦DFSḍ⁵  - Main link. Argument: n (integer) e.g. 49927398716
Ṛ            - Reverse. Casts a number to digits     [6, 1, 7, 8, 9, 3, 7, 2, 9, 9, 4]
     ¦       - Sparse application. Apply the next command to the given indicies
 Ḥ           -   Command: Double
    $        -   Indicies:
  J          -     range(length)...                  [1, 2 , 3, 4, 5, 6, 7, 8, 9, 10, 11]
   Ḥ         -     doubled.                          [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
             - Doubles elements at odd indicies      [6, 2, 7, 16, 9, 6, 7, 4, 9, 18, 4]
      D      - Split each into digits                [6, 2, 7, [1, 6], 9, 6, 7, 4, 9, [1, 8], 4]
       F     - Flatten                               [6, 2, 7, 1, 6, 9, 6, 7, 4, 9, 1, 8, 4]
        S    - Sum                                   70
          ḍ  - Divisible by... 
         ⁵   -   10?                                 1

Ngoài ra, cho 12 byte:

ṚḤJḤ$¦DFSḍ@⁵

3

Hội 8086 , IBM PC DOS,29 28 25 23 byte

; Perform LUHN check
; Input: SI = card num string, CX = length
; Output: ZF = 1 if valid, ZF = 0 if not valid
    LUHN    MACRO
            LOCAL DIGIT_LOOP, EVEN
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 
F7 DA       NEG  DX             ; flip DX to alternate odd/even index
78 06       JS   EVEN           ; if even index, do not double and sum digits 
D0 E0       SHL  AL, 1          ; double the value 
D4 0A       AAM                 ; BCD convert to split digits (ex: 18 = 12H --> 0108H) 
02 DC       ADD  BL, AH         ; add tens digit to running sum 
    EVEN:
02 D8       ADD  BL, AL         ; add ones digit to running sum 
E2 ED       LOOP DIGIT_LOOP 
93          XCHG BX, AX         ; sum is in BL, move to AL for conversion
D4 0A       AAM                 ; BCD convert AL, set ZF=1 if low digit is 0
    ENDM

Sử dụng (lạm dụng) các hướng dẫn BCD-to-binary của x86 để xử lý việc tách và modulo 10kiểm tra chữ số riêng lẻ . Nó chỉ ra rằng AAMvà các AADhướng dẫn thực hiện chuyển đổi BCD / nhị phân các giá trị byte (có thể rất tiện dụng) mặc dù chúng không được ghi lại hoặc mô tả là thực hiện chức năng đó một cách khái quát.

Đối với tất cả các phiên bản chính thức của IBM / MS DOS, AXBXđược khởi tạo 0000khi khởi động ( ref , ref ) và DXđến CS, đó là một giá trị 12-bit để đảm bảo được non-zero và tích cực. Đây là cách chúng ta có thể đảm bảo BX0và có thể lật / flop DXđể xác định chẵn / lẻ chữ số nơi.

Ví dụ đầu ra:

nhập mô tả hình ảnh ở đây

Tải xuống chương trình thử nghiệm IBM PC DOS của LUHN.COM .


2

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)}

cầu nguyện:

c("79927398713")
  • đảo ngược ("79927398713") = 31789372997
  • s (0), s.tail: (3) (1789372997)
  • trượt (2,2) = (17 89 37 29 97)
  • bản đồ (q ((n (0) -48 * 2 + n (1) -48)) => q (('1' - '0') * 2) + '7' - '0') = 1 * 2 + 7

2

JavaScript 1.8: 106 ký tự

Đây là một giải pháp ban đầu tôi đã đưa ra trước khi tôi tìm thấy bài đăng này:

function(n){return!(n.split('').reverse().reduce(function(p,c,i){return(+c&&((c*(1+i%2)%9)||9))+p},0)%10)}

Hình thức dễ đọc:

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?
}


2

Võng mạc , 43 42 byte

Retina là (nhiều) mới hơn so với thách thức này.


;
r`(.);.
$1$&
\d
$*
1+
$.&
.
$*
$
$._
0$

Các dòng trống hàng đầu là đáng kể.

In 0cho giả và 1cho kết quả trung thực.

Hãy thử trực tuyến! (Sửa đổi một chút để chạy tất cả các trường hợp thử nghiệm cùng một lúc.)

Giải trình


;

Chèn ;vào mọi vị trí để tách các chữ số.

r`(.);.
$1$&

Từ right, chúng tôi liên tục ghép hai chữ số và nhân đôi số còn lại. Bằng cách này, chúng tôi tránh được sự đảo ngược đắt tiền của danh sách.

\d
$*

Chúng tôi khớp từng chữ số và chuyển đổi nó thành nhiều chữ số đó 1(nghĩa là chúng tôi chuyển đổi từng chữ số thành đơn vị).

1+
$.&

Điều này khớp với từng số đơn vị và chuyển đổi nó thành số thập phân bằng cách thay thế nó bằng độ dài của nó. Cùng với giai đoạn trước, điều này thêm các chữ số nhân đôi.

.
$*

Một lần nữa, chúng tôi khớp mọi nhân vật và biến nó thành nhiều 1s. Đó là chúng tôi chuyển đổi từng chữ số riêng lẻ trở lại unary. Điều này cũng phù hợp với các ;dấu phân cách, được coi là số không trong chuyển đổi, có nghĩa là chúng bị xóa đơn giản. Vì tất cả các số đơn vị hiện đang bị đè bẹp với nhau, chúng tôi đã tự động thêm các đại diện đơn nhất của tất cả các chữ số lại với nhau.

$
$._

Cuối cùng, chúng tôi chèn độ dài của toàn bộ chuỗi, tức là biểu diễn thập phân của tổng kiểm tra đơn.

0$

Cuối cùng, chúng tôi đếm số lượng các trận đấu của regex này, tức là chúng tôi kiểm tra xem biểu diễn thập phân kết thúc bằng 0, in 0hay 1tương ứng.


2

Powershell, 74 byte

param($s)$s[$s.Length..0]|%{(1+$i++%2)*"$_"}|%{$r+=$_-9*($_-gt9)}
!($r%10)

Giải trình

  1. cho mỗi char của một chuỗi đối số, theo thứ tự ngược lại
  2. lấy một chữ số có giá trị gấp đôi của một chữ số
  3. một giá trị kép của một chữ số không thể lớn hơn 18. Do đó, chúng tôi tích lũy một giá trị trừ 9 nếu giá trị> 9
  4. trả về true nếu phần còn lại của phép chia 10 là 0

Kịch bản kiểm tra

$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"
}

Đầu ra

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



1

GNU sed, 140 byte

(bao gồm +1 cho -rcờ)

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 gần như không bao giờ là ngôn ngữ tự nhiên nhất cho số học, nhưng ở đây chúng tôi đi:

#!/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/

1

APL, 38 byte

d←10∘⊥⍣¯1⋄{0=10|+/+/d x×1+~2|⍳⍴x←⌽d ⍵}

mong đợi số này là một số, không phải là một chuỗi, nhưng đó chỉ là do tryAPL (có thể hiểu được) không thực hiện

giảm hơn nữa, tôi chắc chắn


1

PHP - 136 ký tự

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);}

1

MATL , 23 20 byte (không cạnh tranh)

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

Hãy thử trực tuyến!

Đầu ra 1 cho một số hợp lệ, 0 nếu không.

Đã lưu ba byte nhờ đề xuất của Luis Mendo.

Giải trình

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

1

Thạch , 14 byte

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

Hãy thử trực tuyến!

Giải trình:

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

Tại sao điều này không cạnh tranh?
Mudkip201

@ Mudkip201 Sửa lỗi cho tôi nếu tôi sai, nhưng phiên bản Jelly này không tồn tại khi câu hỏi được hỏi, vì vậy nó không hợp lệ cho câu hỏi.
ellie

3
Khá chắc chắn rằng có một sự đồng thuận meta nói rằng các ngôn ngữ được tạo ra sau thử thách không còn là "không cạnh tranh" nữa
Mudkip201
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.