Algoritma Luhn untuk memverifikasi nomor kartu kredit, dll


50

Tantangan

Tulis program atau fungsi terpendek untuk menghitung Algoritma Luhn untuk memverifikasi nomor (kartu kredit).

Algoritma Luhn menjelaskan

Dari RosettaCode , algoritme ini untuk tujuan tantangan ini ditentukan seperti itu, dengan contoh input dari 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

Aturan IO

Input : Suatu string atau angka (pilihan Anda), dalam format input / output pilihan bahasa Anda

Output : Nilai true atau falsy , masing-masing, yang menunjukkan apakah input valid atau tidak menurut tes di atas.

Catatan / Tips

  • Cobalah untuk tidak secara sengaja memposting kartu kredit atau nomor akun Anda sendiri, jika Anda menggunakannya untuk menguji :)

  • Jika input tidak valid dan tidak mungkin diproses dengan algoritma yang ditentukan (yaitu terlalu pendek untuk bekerja), Anda dapat melakukan apa pun yang Anda inginkan, termasuk meledakkan komputer saya.

  • Namun , peluru sebelumnya tidak berarti bahwa bahasa Anda dapat melakukan apa pun yang diinginkan dengan Angka yang terlalu besar untuk ditangani. Jika bahasa Anda tidak mampu menangani test case, maka pertimbangkan untuk mengambil string sebagai input.

Contohnya

Contoh berikut divalidasi dengan skrip Python ini ; jika Anda merasa ada yang salah atau memiliki pertanyaan, cukup 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  **

** sesuai dengan implementasi Python, tetapi Anda dapat melakukan apa saja karena ini terlalu pendek untuk memenuhi syarat oleh kepatuhan yang ketat terhadap spesifikasi.


Jika salah satu di atas membatalkan jawaban yang ada (meskipun saya yakin itu tidak mungkin), maka jawaban tersebut masih valid. Namun, jawaban baru , agar valid, harus mengikuti spesifikasi di atas.

Papan peringkat

Jawaban:


21

Golfscript - 24 karakter

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

Penjelasan:

  1. -1% membalikkan string
  2. {memulai sebuah blok (yang kami gunakan sebagai sebuah loop). Setiap karakter dalam string didorong karena nilai ascii.
    1. 2+ menambahkan 2. (nilai ascii dari digit adalah 48 + n, jadi kami memiliki 50 + n sekarang dan digit terakhir adalah n)
    2. 0!:0 membalikkan nilai 0 dan menyimpannya (semuanya adalah variabel), jadi kita memiliki 1 pada iterasi pertama, 0 pada yang kedua, dll.
    3. )* menambahkan satu ke nilai ini dan mengalikannya, jadi kita kalikan dengan 2, lalu 1, lalu 2, dll.
    4. 109% adalah modulo sisa 109. Ini hanya mempengaruhi nilai 5-9 yang telah digandakan dan menguranginya ke nilai yang benar.
    5. + menambahkan nilai ini ke jumlah berjalan
  3. }*mengakhiri blok dan melakukan operasi 'lipat'. Pertama, karakter pertama didorong (karena kita telah terbalik, ini adalah digit periksa). Kemudian, secara bergantian mendorong dan menjalankan blok. Jadi, kita menggunakan nilai ascii karakter pertama sebagai nilai awal untuk jumlah berjalan.
  4. 10% mengambil modulo 10 sisanya.
  5. 8= akan mengembalikan 1 jika nilainya 8. Kami menggunakan ini karena kami tidak menormalkan karakter terdorong pertama (digit periksa).

Orang mungkin berpikir bahwa kita bisa menggunakan 8-bukannya 2+untuk menyimpan karakter dengan mengubah 109%ke 89%, kecuali maka kita perlu menambahkan spasi sehingga -adalah pengurangan (bukan -0).


11

GolfScript, 44 karakter

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

Komentar yang dipilih

Menariknya, dua item pertama di bawah ini menunjukkan tiga kegunaan yang sama sekali berbeda dari %operator: pemilihan array, peta, dan mod. Sebagian besar operator GolfScript "peka konteks", memberi mereka perilaku yang sangat berbeda tergantung pada jenis argumennya.

  1. -1%membalikkan string. Ini penting karena pasangan digit dihitung dari kanan.
  2. {16%}% mengubah semua angka ASCII menjadi angka, dengan memodifikasinya dengan 16.
  3. 2/ membagi array menjadi kelompok-kelompok 2.
  4. 1,adalah cara yang murah untuk dilakukan [0].
  5. \+secara efektif menambahkan awal 0 ke array digit. Ini dilakukan dengan menukar lalu menggabungkan.

Angka 0 didahului untuk persiapan lipatan yang akan datang berikutnya. Daripada mengambil nilai awal yang eksplisit, lipatan GolfScript menggunakan item pertama dalam array sebagai nilai awal.

Sekarang, mari kita lihat fungsi lipatan sebenarnya. Fungsi ini mengambil dua argumen: nilai yang dilipat, dan item saat ini pada array (yang dalam hal ini akan menjadi array 2 atau (tidak umum) 1, karena 2/sebelumnya). Mari kita asumsikan argumennya 1 [2 3].

  1. (\.memisahkan elemen array paling kiri, memindahkan array yang tersisa ke depan, lalu menyalinnya. Stack sekarang terlihat seperti: 1 2 [3] [3].
  2. The ifmemeriksa apakah array kosong (yang merupakan kasus untuk kelompok terakhir ketika berhadapan dengan nomor rekening aneh berukuran). Jika demikian, maka tidak ada pemrosesan khusus yang terjadi (lepas dari array kosong).
  3. Untuk grup genap:
    1. 0= meraih elemen pertama (hanya, dalam hal ini) dari array. 1 2 3
    2. 2* menggandakan jumlahnya. 1 2 6
    3. .9>9*- kurangi 9 dari angka jika lebih besar dari 9. Diimplementasikan sebagai: salin nomornya, bandingkan dengan 9, kalikan hasilnya (yang 0 atau 1) dengan 9, lalu kurangi. 1 2 6
    4. + akhirnya menambahkan itu ke nomor pertama. 1 8
  4. +(setelah if) menambahkan hasil ifke nilai asli, menghasilkan nilai yang dilipat baru.

Setelah lipat selesai, kita cukup mod dengan 10 ( 10%), dan meniadakan hasilnya ( !), sehingga kita mengembalikan 1 jika jumlah adalah kelipatan 10.


Ini sepertinya mengembalikan 0 untuk contoh nomor di wikipedia (49927398716)
gnibbler

nm. Saya lupa menggunakanecho -n
gnibbler

1
@gnibbler: Haha, gagal. :-P (Serius, saya disengat oleh yang itu juga, dalam pengujian awal saya.)
Chris Jester-Young

1
Beberapa tempat untuk menyimpan beberapa karakter mudah di sini. -1% 2/dapat digabungkan menjadi -2/. 1,dapat diganti dengan 0(0 dipaksa ke array, lalu +digabungkan). 9>9*-dapat diganti dengan 9>+(karena kami hanya peduli dengan digit terakhir). Juga, memeriksa panjang ganjil agak panjang, menggunakan .,2%,\+lebih pendek. Setelah melakukan ini, kita juga bisa mengubah {16%}%dan (\0=menjadi {16}/(di dalam lingkaran). Setelah Anda melakukan semua itu, itu akan terlihat seperti ini: .,2%,\+-2/0\+{{16%}/2*.9>+++}*10%!.
Nabb

@Nabb: Terima kasih! Saya akan memasukkan mereka ke dalam solusi saya, meskipun sepertinya Anda sudah memiliki yang menendang pantat serius. :-)
Chris Jester-Young

11

Python, 73 69 karakter

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

4
Anda dapat menyimpan dua karakter lagi dengan tidak mengulangi mundur: D[-2::-2]-> D[1::2]karena urutan jumlah tidak penting :)
ThinkChaos

==0dapat disingkat menjadi<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 karakter:

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

Tidak terlalu buruk untuk kode golf n00b dalam bahasa yang diketik secara statis, saya harap.

Ini dapat dikurangi menjadi 100 :

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

Itu ide yang bagus, dan pendekatan yang menarik, tetapi tampaknya tidak berhasil. Setidaknya tidak dengan beberapa tes saya. Sepertinya "i" di lambda pertama Anda seharusnya merupakan indeks karakter dalam string. Apakah itu berfungsi sebagaimana mestinya? Jika demikian, mengapa Anda membalikkan string hanya untuk kemudian memodifikasinya berdasarkan posisi indeks? Tampaknya agak berlebihan, bukan?
Nellius

Saya hanya menguji salah satu kartu kredit saya dan beberapa kesalahan off dengan satu dari itu TBH. (Menggunakan debugger VS 2008) Algoritma ini seharusnya menggandakan setiap digit kedua dimulai dengan digit TERAKHIR. Jika saya tidak membalik string, itu akan menjadi salah untuk string dengan panjang aneh.
mootinator

Ternyata saya memang punya hasil i%2<1?1:2mundur. Terima kasih.
mootinator

8

Golfscript - 34 karakter

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

Contoh nomor dari halaman 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

Ini .+(9%)sangat inovatif (bagi saya, sih). Saya suka! +1
Chris Jester-Young

Namun, GolfScript membutuhkan operator partisi, jadi Anda tidak perlu melakukan ini "drop end item off and repeat" nonsense. :-)
Chris Jester-Young

1
@ Chris, saya belajar tentang itu bertahun-tahun yang lalu disebut "mengusir sembilan". Ini adalah cara yang rapi untuk memeriksa ulang penambahan dan perkalian tangan lama
gnibbler

3
Ini tidak akan berfungsi untuk nilai 0 menjadi dua kali lipat ( 0(9%)adalah 9 dan bukan 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 karakter

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

Anda mungkin tahu tentang ini, tetapi Anda bisa melakukan .sum alih-alih .inject (: +) untuk menghemat 7 byte
Håvard Nygård

7

Haskell, 96 byte

Pasti ada cara yang lebih baik / lebih pendek, tapi inilah solusi Haskell saya dalam 96 karakter :

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

Sayangnya digitToIntfungsi ini hanya bisa digunakan jika Anda import Data.Charpertama kali. Kalau tidak, saya bisa turun ke 88 karakter dengan mengganti ((+(-48)).fromEnum)dengan digitToInt.


6

Windows PowerShell, 82

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

Sejarah:

  • 2011-02-13 03:08 (84) Upaya pertama.
  • 2011-02-13 12:13 (82) Saya tidak perlu bergabung, karena ruang tidak ada salahnya. +1 + +3masih bisa dievaluasi.

5

Q, 63

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

pemakaian

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 dengan {0=mod[sum"J"$raze($)($)x*#:[x]#1 2]10}"I"$'(|)cara berbeda untuk menggandakan indeks ganjil.
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;}

Lebih jelas:

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←⍎¨⍵}

Tampilan meledak

{                     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

Contohnya

      {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

Termasuk +1 untuk -p

Berikan masukan pada STDIN:

luhn.pl <<< 79927398713

luhn.pl:

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

Bisakah Anda jelaskan bagaimana cara kerjanya? Anda tampaknya mengalami decrementing oleh pertandingan dan kemudian juga dengan waktu pertandingan 1.2 tetapi hanya di posisi yang benar. Kenapa 1.2? Bukankah seharusnya begitu $=-=-$&-$&*/\G(..)+$/?
msh210

3
@ msh210: Ini mengkodekan efek dari perkalian dengan 2. 0..4* 2 memberi 0, 2, 4, 6, 8tetapi 5..9memberikan 10,12,14,16,18jumlah 1 3 5 7 9yang memiliki angka terakhir 11 13 15 17 19yang sama dengan nilai yang sama seperti 0..9 * 2.2jika Anda memotong ke integer. Yang pertama $&sudah berkontribusi faktor 1, sehingga koreksi oleh 1.2masih diperlukan. $=hanya dapat menahan bilangan bulat dan dimulai dengan nilai yang berakhir pada 0 sehingga menangani pemotongan. Nilai-nilai negatif diperlukan karena /\G/regex mengubah $&masih pada tumpukan evaluasi sehingga mereka perlu diubah
Ton Hospel

Oh Cemerlang! Dan terima kasih atas penjelasannya.
msh210

3

JavaScript (ES6), 61 byte

Non-bersaing, karena JavaScript sangat berbeda pada 2011.

Jumlah digit 2*nadalah 2*njika n in 0..4, 2*n-9jika n in 5..9. Yang mengatakan, semua jumlah dapat dihitung dalam satu langkah.

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

3

Jelly , 12 11 byte

ṚḤJḤ$¦DFS⁵ḍ

Cobalah online! (dengan semua kasus uji)

Bagaimana itu bekerja

ṚḤ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

Atau, untuk 12 byte:

ṚḤJḤ$¦DFSḍ@⁵

3

x86-16 ASM , IBM PC DOS, 23 byte

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

Menggunakan (menyalahgunakan) instruksi BCD-ke-biner x86 AAMuntuk menangani pemisahan dan modulo 10pengecekan digit individu .

Masukkan num string pointer kartu SI, panjang CX. Output: ZFjika valid.

Contoh hasil uji program:

masukkan deskripsi gambar di sini

Unduh program uji IBM PC DOS 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)}

doa:

c("79927398713")
  • membalikkan ("79927398713") = 31789372997
  • s (0), s.tail: (3) (1789372997)
  • geser (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

2

JavaScript 1.8: 106 karakter

Ini adalah solusi orisinal yang saya buat sebelum saya menemukan posting ini:

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

Formulir yang dapat dibaca:

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

Retina , 43 42 byte

Retina (jauh) lebih baru dari tantangan ini.


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

Baris kosong terkemuka adalah signifikan.

Mencetak 0untuk hasil palsu dan 1untuk hasil yang benar.

Cobalah online! (Sedikit dimodifikasi untuk menjalankan semua test case sekaligus.)

Penjelasan


;

Masukkan ;di setiap posisi untuk memisahkan digit.

r`(.);.
$1$&

Dari belakang r, kami berulang kali mencocokkan dua digit dan menggandakan yang kiri. Dengan cara ini kami menghindari pembalikan daftar yang mahal.

\d
$*

Kami mencocokkan setiap digit dan mengonversinya menjadi banyak 1(yaitu, kami mengonversi setiap digit menjadi unary).

1+
$.&

Ini cocok dengan masing-masing nomor unary dan mengubahnya kembali menjadi desimal dengan menggantinya dengan panjangnya. Bersama dengan tahap sebelumnya, ini menambahkan digit dua kali lipat.

.
$*

Sekali lagi, kami mencocokkan setiap karakter dan mengubahnya menjadi banyak 1. Yaitu kita mengonversi setiap digit secara individual kembali ke unary. Ini juga cocok dengan ;pemisah, yang diperlakukan sebagai nol dalam konversi, yang berarti mereka hanya dihapus. Karena semua angka unary sekarang terjepit bersama, kami secara otomatis telah menambahkan representasi unary dari semua angka.

$
$._

Pada akhirnya, kita memasukkan panjang seluruh string, yaitu representasi desimal dari checksum unary.

0$

Akhirnya kami menghitung jumlah kecocokan dari regex ini, yaitu kami memeriksa apakah representasi desimal berakhir 0, dicetak 0atau 1sesuai.


2

Powershell, 74 byte

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

Penjelasan

  1. untuk setiap karakter string argumen, dalam urutan terbalik
  2. dapatkan satu digit nilai ganda dari satu digit
  3. nilai ganda digit tidak boleh lebih besar dari 18. Oleh karena itu, kami mengakumulasikan nilai minus 9 jika nilai> 9
  4. return true jika sisa pembagian dengan 10 adalah 0

Skrip uji

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

Keluaran

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

2

05AB1E , 12 10 byte

RSāÈ>*SOTÖ

Cobalah online! atau sebagai Test Suite

Penjelasan

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


1

GNU sed, 140 byte

(termasuk +1 untuk -rbendera)

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 hampir tidak pernah merupakan bahasa yang paling alami untuk aritmatika, tetapi di sini kita mulai:

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

mengharapkan angka sebagai angka, bukan string, tetapi itu hanya karena tryAPL (dimengerti) tidak diterapkan

lebih lanjut direduksi, saya yakin ...


1

PHP - 136 karakter

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 (tidak bersaing)

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

Cobalah online!

Output 1 untuk angka yang valid, 0 sebaliknya.

Disimpan tiga byte berkat saran Luis Mendo.

Penjelasan

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

Jelly , 14 byte

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

Cobalah online!

Penjelasan:

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

Mengapa ini tidak bersaing?
mudkip201

@ mudkip201 Perbaiki saya jika saya salah, tetapi versi Jelly ini tidak ada saat pertanyaan diajukan, jadi tidak valid untuk pertanyaan itu.
ellie

3
Cukup yakin ada konsensus meta yang mengatakan bahwa bahasa yang dibuat setelah tantangan tidak lagi 'tidak bersaing'
mudkip201
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.