Kredi kartı numaralarını, vb. Doğrulamak için Luhn algoritması


49

Meydan okuma

(Kredi kartı) numaralarını doğrulamak için Luhn Algoritmasını hesaplamak için en kısa programı veya işlevi yazın .

Luhn algoritması açıkladı

RosettaCode'dan , bu zorluğun amaçları için bu algoritma, aşağıdaki gibi örnek girdiyle belirtilir 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 Kuralları

Giriş : Dilinizin seçim / çıkış biçiminde bir dize veya sayı (seçiminiz)

Çıktı : Girdilerin yukarıdaki teste göre geçerli olup olmadığını gösteren sırayla veya yanlış değer .

Notlar / İpuçları

  • Yanlışlıkla test etmek için kullanıyorsanız, kendi kredi kartınızı veya hesap numaralarınızı göndermemeye çalışın :)

  • Giriş geçersizse ve belirtilen algoritma ile işlem yapmak imkansızsa (yani çalışmak için çok kısa), bilgisayarımı patlatmak da dahil olmak üzere ne istersen yapabilirsin.

  • Bununla birlikte , önceki madde işareti, dilinizin, işlemesi için çok büyük olan Numaralarla istediğini yapabileceği anlamına gelmez. Diliniz bir test senaryosunu kullanabiliyorsa, bir dize giriş olarak alın.

Örnekler

Aşağıdaki örnekler bu Python betiği ile doğrulandı ; Eğer birinin yanlış olduğunu ya da bir sorusu olduğunu düşünüyorsanız, sadece 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  **

** Python uygulamasına göre, ancak şartnameye katı bir şekilde bağlı kalmaya uygun olmadığı için herhangi bir şey yapabilirsiniz.


Yukarıdakilerden herhangi biri mevcut cevapları geçersiz kılarsa (bunun mümkün olmamasına inandığım halde), bu cevaplar hala geçerlidir. Ancak, geçerli olabilmek için yeni cevapların yukarıdaki şartnameye uyması gerekir.

Liderler Sıralaması

Yanıtlar:


21

Golfscript - 24 karakter

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

Açıklama:

  1. -1% dizeyi tersine çevirir
  2. {Bir blok (döngü olarak kullandığımız) başlatır. Dizelerdeki her karakter ascii değeri olarak basılır.
    1. 2+ 2 ekler (bir basamağın ascii değeri 48 + n'dir, bu nedenle şimdi 50 + n var ve son rakam n)
    2. 0!:0 0 değerini tersine çevirir ve saklar (her şey değişkendir), bu nedenle ilk yinelemede 1, ikincide 0 olur, vb.
    3. )* bu değere bir tane ekler ve çoğaltır, bu yüzden 2, sonra 1, ardından 2 vb.
    4. 109% geri kalan modulo 109'dur. Bu, yalnızca iki katına çıkmış 5-9 değerlerini etkiler ve bunları doğru değere düşürür.
    5. + bu değeri koşu topluluğuna ekler
  3. }*bloğu sonlandırır ve 'katlama' işlemi yapar. İlk olarak, ilk karakter itilir (ters çevrildiğimizden beri bu kontrol basamağıdır). Ardından, bloğu iterek ve uygulayarak değiştirin. Bu nedenle, ilk karakterin ascii değerini, koşu toplamı için başlangıç ​​değeri olarak kullanıyoruz.
  4. 10% geri kalan modulo 10'u alır.
  5. 8= değer 8 ise 1 değerini döndürür. İlk basılan karakteri (kontrol basamağı) normalleştirmediğimiz için bunu kullanırız.

Bir kullandığımız diye düşünebilir 8-yerine 2+değiştirerek bir karakteri kurtarmak için 109%için 89%böylece o zaman bir boşluk eklemek gerekir hariç -(yerine çıkarma olduğunu -0).


11

GolfScript, 44 karakter

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

Seçilmiş yorum

İlginç bir şekilde, aşağıdaki ilk iki öğe %operatörün tamamen farklı üç kullanımını göstermektedir : dizi seçimi, harita ve mod. Çoğu GolfScript operatörü "bağlam duyarlı" dır ve bağımsız değişkenlerin ne türlerine bağlı olarak onlara birbirinden farklı davranışlar sunar.

  1. -1%dizeyi tersine çevirir. Rakam çiftleri sağdan sayıldığı için bu önemlidir.
  2. {16%}% Tüm ASCII basamaklarını 16 ile modlandırarak sayılara dönüştürür.
  3. 2/ diziyi 2 kişilik gruplar halinde böler.
  4. 1,yapmak için ucuz bir yoldur [0].
  5. \+0 değerini basamak dizisine etkili bir şekilde hazırlar. Bunu takas ederek birleştirerek yapar.

0 sonraki gelen kat için hazırlık hazırlanır. Açık bir başlangıç ​​değeri almak yerine, GolfScript'in katlaması, dizideki ilk öğeyi başlangıç ​​değeri olarak kullanır.

Şimdi gerçek katlama fonksiyonuna bakalım. Bu işlev iki argüman alır: katlanmış değer ve dizideki geçerli öğe (bu durumda, önceki durumdan dolayı 2 veya (nadiren) 1 dizisi olur 2/). Argümanların olduğunu varsayalım 1 [2 3].

  1. (\.en soldaki dizi öğesini ayırır, kalan diziyi öne taşır, sonra kopyalar. Yığın şimdi şöyle görünür: 1 2 [3] [3].
  2. ifKontrol dizisi (tek boyutlu bir hesap numarası ile ilgili son grup için durum olan) boşsa. Öyleyse, özel bir işlem gerçekleşmez (sadece boş diziyi açın).
  3. Çift bir grup için:
    1. 0= dizinin ilk (yalnızca bu durumda) öğesini alır. 1 2 3
    2. 2* sayıyı ikiye katlar. 1 2 6
    3. .9>9*- 9'dan büyükse sayıyı 9 çıkarır: Uygulanan: sayıyı kopyala, 9 ile karşılaştır, sonucu (ya 0 ya da 1'dir) 9 ile çarp, sonra çıkar. 1 2 6
    4. + Sonunda ilk sayıya ekler. 1 8
  4. +(sonrasında if) sonucunu iforijinal değerine ekler , yeni katlanmış değere yol açar.

Katlama işlemi tamamlandıktan sonra, sadece 10 ( 10%) ile mod yaparız ve sonucu ( !) reddederiz , böylece toplamı 10 katıdır.


Bu, wikipedia'daki (49927398716) örnek numara için 0 döndürüyor gibi görünüyor
gnibbler

mil. echo -n
Kullanmayı

1
@gnibbler: Haha, başarısız ol. :-P (Cidden, benim de ilk testimde buna çok üzüldüm.)
Chris Jester-Young

1
Burada birkaç kolay karakter kaydetmek için birkaç yer. -1% 2/içine birleştirilebilir -2/. 1,ile değiştirilebilir 0(0 bir diziye zorlanır, sonra +birleştirilir). 9>9*-ile değiştirilebilir 9>+(çünkü sadece son rakamla ilgileniyoruz). Ayrıca, tuhaf uzunlukların kontrolü biraz daha uzun, kullanım .,2%,\+ise daha kısa. Bunu yaptıktan sonra, değiştirebiliriz {16%}%ve (\0=içine {16}/(döngünün içinde). Tüm bu yaptıktan sonra, böyle bir şey bakacağız: .,2%,\+-2/0\+{{16%}/2*.9>+++}*10%!.
Nabb

@ Nabb: Teşekkürler! Bunları benim çözümüme dahil edeceğim, görünüşe göre zaten ciddi kıç tekmeleyen birine sahipsin. :-)
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
Geriye doğru döngü yapmadan iki karakter daha kazanabilirsiniz: D[-2::-2]-> D[1::2]toplamın sırası önemli olmadığı için :)
ThinkChaos

==0kısaltılabilir<1
Black Owl Kai

10

Python 3, 77 bayt

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

Değil çok statik olarak yazılan dilde bir kod golf n00b için kötü, umarım.

Bu 100'e düşürülebilir :

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

Bu iyi bir fikir ve ilginç bir yaklaşım, ancak işe yaramadı. En azından birkaç testimle. İlk lambda'nızdaki "i" harfinin karakter dizini olduğu varsayılıyor. Bu olması gerektiği gibi çalışır mı? Öyleyse, neden yalnızca dizeyi tersine çevirirsiniz, sonra dizin konumuna göre değiştirirsiniz? Biraz gereksiz görünüyor, hayır?
Nellius

Kredi kartlarımdan sadece bir tanesini test ettim ve bir kaçını TBH'den bir hata yaptım. (VS 2008 hata ayıklayıcısını kullanarak) Algoritmanın, LAST basamağı ile başlayan her ikinci basamağı ikiye katlaması beklenir. İpi ters çevirmediysem, garip uzunluklu dizeler için yanlış olur.
mootinator

Anlaşılan i%2<1?1:2geriye doğru bir sonuç aldım . Teşekkürler.
mootinator

8

Golfscript - 34 karakter

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

Wikipedia sayfasından örnek numara 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

Bu .+(9%)çok yenilikçi (zaten benim için). Severim! +1
Chris Jester-Young

Yine de GolfScript bölümleme operatörüne ihtiyaç duyuyor, bu yüzden bu "son nesneyi bırakıp saçmalamayı" yapmanız gerekmez. :-)
Chris Jester-Young,

1
@ Chris, yıllar önce "dokuzları dökmek" dendiğini öğrendim.
Uzun süreli

3
Bu iki katına çıkacak 0 değeri için işe yaramaz ( 0(9%)9 ve 0 değil)
Nabb

8

PHP, 108 bayt

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

Muhtemelen bunu biliyorsunuzdur, ancak 7 byte tasarruf etmek için .inject (: +) yerine .sum yapabilirsiniz
Håvard Nygård

7

Haskell, 96 bayt

Daha iyi / daha kısa bir yol olmalı, ancak işte 96 karakterde Haskell çözümüm :

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

Ne yazık ki, digitToIntişlev yalnızca import Data.Charilk önce kullanıyorsanız kullanılabilir . Aksi takdirde ben değiştirerek 88 karakter aşağı alabilir ((+(-48)).fromEnum)ile digitToInt.


6

Windows PowerShell, 82

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

Tarih:

  • 2011-02-13 03:08 (84) İlk deneme.
  • 2011-02-13 12:13 (82) Katılmaya ihtiyacım yok, çünkü boşluklar zarar görmez. +1 + +3hala değerlendirilebilir.

5

Q, 63

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

kullanım

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

{0=mod[sum"J"$raze($)($)x*#:[x]#1 2]10}"I"$'(|)Tek endeksleri iki katına çıkarmak için 47 bayt .
streetster

5

D, 144 bayt

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

Daha okunaklı olmak:

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 bayt

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

Parçalarına ayrıştırılmış görünüm

{                     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

Örnekler

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

1
-2:{0=10|+/⍎¨∊⍕¨⍵×⌽2-2|⍳⍴⍵}⍎¨
17'de

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 bayt

İçin +1 içerir -p

STDIN'e giriş verin:

luhn.pl <<< 79927398713

luhn.pl:

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

Bunun nasıl çalıştığını açıklayabilir misiniz? Maçın ardından ve aynı zamanda 1.2 maç zamanına göre ancak sadece doğru pozisyonlarda azalmış gibi görünüyorsunuz. Neden 1.2? Olmamalı mı $=-=-$&-$&*/\G(..)+$/?
msh210

3
@ msh210: Çarpımın etkisini 2 ile kodlar. 0..4* 2 verir 0, 2, 4, 6, 8ancak hangi toplamı, tam sayıyla kesilmiş gibi aynı değerlere sahip olduğu gibi son rakamları 5..9verir . İlki zaten bir faktöre katkıda bulunuyor , bu yüzden hala bir düzeltme gerekiyor. sadece tamsayıları tutabilir ve 0 ile biten bir değerle başlar, böylece kesmeye özen gösterir. Çünkü negatif değerler ihtiyaç vardır regex herhangi değiştirir onlar değiştirilmesi gerekir böylece değerlendirme yığın hala10,12,14,16,181 3 5 7 911 13 15 17 190..9 * 2.2$&11.2$=/\G/$&
Ton Hospel

Ah. Parlak! Ve açıklama için teşekkürler.
msh210

3

JavaScript (ES6), 61 bayt

Rekabetçi değil, çünkü 2011'de JavaScript çok farklıydı.

Rakamları toplamı 2*nise 2*neğer n in 0..4, 2*n-9eğer n in 5..9. Bununla birlikte, tüm toplamlar bir adımda hesaplanabilir.

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

3

Jöle , 12 11 bayt

ṚḤJḤ$¦DFS⁵ḍ

Çevrimiçi deneyin! (tüm test durumlarıyla)

Nasıl çalışır

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

Alternatif olarak, 12 bayt için:

ṚḤJḤ$¦DFSḍ@⁵

3

8086 Meclisi , IBM PC DOS,29 28 25 23 bayt

; 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

Bireysel basamak bölmeyi işlemek ve modulo 10kontrol etmek için x86'nın BCD-ikili komutlarını kullanır (kötüye kullanır) . Bu çıkıyor AAMve AADtalimatları bunların değil belgelenmiş ya da genel olarak bu işlevi yerine getirebilecek şekilde tarif edilmektedir (rağmen çok kullanışlı olabilir) bayt değerleri BCD / ikili dönüşüm yapmak.

Tüm resmi IBM / MS-DOS versiyonları için, AXve BXbaşlatılır 0000başlangıçta (ilgili ref , ref ) ve DXüzere CSçok sıfır olmayan ve pozitif olması garanti edilen bir 12-bit değeri olan. Bu bizim garanti edemez nasıl BXolduğunu 0ve flop / çevirebilirsiniz DXtek / çift basamaklı yerleri belirlemek için.

Örnek çıktı:

görüntü tanımını buraya girin

LUHN.COM IBM PC DOS test programını indirin.


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

çağırma:

c("79927398713")
  • geri ("79927398713") = 31789372997
  • s (0), ayrıntılı: (3) (1789372997)
  • kayar (2,2) = (17 89 37 29 97)
  • harita (q ((n (0) -48 * 2 + n (1) -48)) => q (('1' - '0') * 2) + '7' - '0') = 1 * 2 + 7

2

JavaScript 1.8: 106 karakter

Bu yazıyı bulamadan önce karşılaştığım özgün bir çözüm:

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

Okunabilir formu:

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 bayt

Retina bu mücadeleden daha yeni.


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

Önde gelen boş satır önemli.

0Sahte ve 1truthy sonuçlar için yazdırır .

Çevrimiçi deneyin! (Tüm test durumlarını bir kerede çalıştırmak için hafifçe değiştirilmiş.)

açıklama


;

;Rakamları ayırmak için her konuma yerleştirin .

r`(.);.
$1$&

Dan ruş, biz tekrar tekrar iki basamak ve çift sol adresle aynı olmalıdır. Bu şekilde listenin pahalı bir şekilde ters çevrilmesini önleriz.

\d
$*

Her bir basamağa eşleşip onu birçok 1s'ye dönüştürürüz (yani, her basamağı birliğe çeviririz).

1+
$.&

Bu, her bir tek sayı ile eşleşir ve uzunluğu ile değiştirilerek tekrar ondalık değerine dönüştürülür. Önceki aşama ile birlikte, iki katına rakam ekler.

.
$*

Yine, her karakterle eşleşip onu bu kadar çok karaktere dönüştürüyoruz 1. Yani her bir basamağı ayrı ayrı unary'e çeviriyoruz. Bu aynı zamanda ;dönüşümde sıfır olarak kabul edilen ayırıcılarla da eşleşir , bu da basitçe kaldırıldıkları anlamına gelir. Tüm tekli sayılar şimdi birbirine çarptığından, tüm sayıların tekli temsillerini birlikte otomatik olarak ekledik.

$
$._

Sonunda, tüm dizenin uzunluğunu, yani tekdüze sağlama toplamının ondalık gösterimini yerleştiririz.

0$

Son olarak, bu regex'in eşleşme sayısını sayarız, yani ondalık gösterimin 0, yazdırmanın 0veya 1buna göre mi biteceğini kontrol ederiz .


2

Powershell, 74 bayt

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

açıklama

  1. Bir argüman dizesinin her karakteri için, ters sırada
  2. rakamın çift değerinde bir rakam almak
  3. bir hanenin çift değeri 18'den büyük olamaz. Bu nedenle,> 9 ise eksi 9 değerini biriktiririz.
  4. bölümün kalanı 10 ise 0 olur

Test komut dosyası

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

Çıktı

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 bayt

RSāÈ>*SOTÖ

Çevrimiçi deneyin! veya Test Paketi olarak

açıklama

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 bayt

( -rbayrak için +1 dahil )

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, neredeyse hiçbir zaman aritmetik için en doğal dil değildir, ancak işte başlıyoruz:

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

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

Sayıyı bir dize olarak bekler, ancak bunun nedeni yalnızca tryAPL'in (anlaşılır şekilde) uygulamamasıdır.

daha da azaltılabilir, eminim…


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 bayt (yarışmayan)

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

Çevrimiçi deneyin!

Geçerli bir sayı için 1, aksi takdirde 0 çıktı.

Luis Mendo'nun önerileri sayesinde üç bayt kurtardı.

açıklama

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

Jöle , 14 bayt

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

Çevrimiçi deneyin!

Açıklama:

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

Bu neden rekabet etmiyor?
mudkip201

@ mudkip201 Yanlışysam düzeltin, ancak soru sorulduğunda Jelly'in bu sürümü mevcut değildi, bu yüzden soru için geçerli değil.
ellie,

3
Elbette, meydan okuma sonrasında yapılan dillerin artık 'rekabet etmeyen' olmadığını söyleyen bir fikir birliği olduğu
kesindi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.