Der Luhn - Algorithmus zur Überprüfung von Kreditkartennummern usw


49

Herausforderung

Schreiben Sie das kürzeste Programm oder die kürzeste Funktion zur Berechnung des Luhn-Algorithmus zur Überprüfung von Kreditkartennummern.

Luhn-Algorithmus erklärt

Von RosettaCode wird dieser Algorithmus für die Zwecke dieser Herausforderung als solcher angegeben, mit der Beispieleingabe von 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-Regeln

Eingabe : Eine Zeichenfolge oder Zahl (Ihre Wahl) im Eingabe- / Ausgabeformat Ihrer Sprache

Ausgabe : Ein wahrer oder falscher Wert , der angibt, ob die Eingabe gemäß dem obigen Test gültig ist oder nicht.

Hinweise / Tipps

  • Versuchen Sie nicht, versehentlich Ihre eigenen Kreditkarten- oder Kontonummern zu veröffentlichen, wenn Sie diese zum Testen verwenden :)

  • Wenn die Eingabe ungültig und mit dem angegebenen Algorithmus nicht zu verarbeiten ist (dh zu kurz, um damit zu arbeiten), können Sie alles tun, was Sie wollen, auch meinen Computer in die Luft jagen.

  • Das vorige Aufzählungszeichen bedeutet jedoch nicht, dass Ihre Sprache mit Zahlen, die zu groß sind, um sie verarbeiten zu können, tun kann, was sie will. Wenn Ihre Sprache keinen Testfall verarbeiten kann, sollten Sie eine Zeichenfolge als Eingabe verwenden.

Beispiele

Die folgenden Beispiele wurden mit diesem Python-Skript überprüft. Wenn Sie der Meinung sind, dass eine falsch ist oder eine Frage hat, senden Sie einfach einen Ping an @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  **

** Gemäß der Python-Implementierung können Sie jedoch alles Mögliche tun, da diese zu kurz sind, um durch strikte Einhaltung der Spezifikation in Frage zu kommen.


Wenn eine der oben genannten Antworten vorhandene Antworten ungültig macht (obwohl ich glaube, dass dies nicht möglich sein sollte), sind diese Antworten weiterhin gültig. Jedoch neue Antworten, um gültig zu sein, sollten die Spezifikation oben folgen.

Bestenliste

Antworten:


21

Golfscript - 24 Zeichen

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

Erläuterung:

  1. -1% kehrt die Zeichenfolge um
  2. {beginnt einen Block (den wir als Schleife verwenden). Jedes Zeichen in der Zeichenfolge wird als ASCII-Wert verschoben.
    1. 2+ addiert 2. (der ASCII-Wert einer Ziffer ist 48 + n, also haben wir jetzt 50 + n und die letzte Ziffer ist n)
    2. 0!:0 Invertiert den Wert von 0 und speichert ihn (alles ist eine Variable), sodass wir bei der ersten Iteration 1, bei der zweiten 0 usw. haben.
    3. )* addiert eins zu diesem Wert und multipliziert ihn, also multiplizieren wir mit 2, dann 1, dann 2 usw.
    4. 109% ist Rest Modulo 109. Dies betrifft nur die Werte 5-9, die verdoppelt und auf den korrekten Wert reduziert wurden.
    5. + addiert diesen Wert zur laufenden Summe
  3. }*Beendet den Block und führt eine Fold-Operation aus. Zuerst wird das erste Zeichen gedrückt (da wir umgekehrt haben, ist dies die Prüfziffer). Drücken Sie dann abwechselnd auf den Block und führen Sie ihn aus. Daher verwenden wir den ASCII-Wert des ersten Zeichens als Startwert für die laufende Summe.
  4. 10% nimmt den Rest modulo 10.
  5. 8= Gibt 1 zurück, wenn der Wert 8 ist. Wir verwenden dies, weil wir das erste gedrückte Zeichen (die Prüfziffer) nicht normalisiert haben.

Man könnte meinen, die wir verwenden könnten , 8-anstatt 2+ein Zeichen zu speichern , indem Sie 109%auf 89%, es sei denn dann würden wir einen Raum hinzufügen müssen , so dass das -ist Subtraktion (statt -0).


11

GolfScript, 44 Zeichen

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

Ausgewählter Kommentar

Interessanterweise zeigen die ersten beiden Punkte unten drei völlig unterschiedliche Verwendungen des %Operators: Array-Auswahl, Map und Mod. Die meisten GolfScript-Operatoren sind "kontextsensitiv" und verhalten sich je nach Art der Argumente sehr unterschiedlich.

  1. -1%kehrt die Zeichenfolge um. Dies ist wichtig, da die Ziffernpaare von rechts gezählt werden.
  2. {16%}% konvertiert alle ASCII-Ziffern in Zahlen, indem sie mit 16 modifiziert werden.
  3. 2/ Teilt das Array in 2er-Gruppen auf.
  4. 1,ist ein billiger Weg, dies zu tun [0].
  5. \+Stellt effektiv die 0 vor das Ziffern-Array. Dies geschieht durch Vertauschen und Verketten.

Die 0 wird in Vorbereitung auf die nächste Falte vorangestellt. Anstatt einen expliziten Anfangswert zu verwenden, verwendet GolfScript's Fold das erste Element im Array als Anfangswert.

Schauen wir uns nun die eigentliche Falzfunktion an. Diese Funktion akzeptiert zwei Argumente: den gefalteten Wert und das aktuelle Element im Array (in diesem Fall ein Array von 2 oder (ungewöhnlich) 1, da es sich um das 2/frühere handelt). Nehmen wir an, die Argumente sind 1 [2 3].

  1. (\.Teilt das Array-Element ganz links auf, verschiebt das verbleibende Array nach vorne und kopiert es dann. Stapeln Sie jetzt aussieht: 1 2 [3] [3].
  2. Das ifprüft, ob das Array leer ist (was bei der letzten Gruppe der Fall ist, wenn es sich um eine ungerade Kontonummer handelt). In diesem Fall findet keine spezielle Verarbeitung statt (entfernen Sie einfach das leere Array).
  3. Für eine gerade Gruppe:
    1. 0= greift nach dem ersten (in diesem Fall einzigen) Element des Arrays. 1 2 3
    2. 2* verdoppelt die Zahl. 1 2 6
    3. .9>9*- subtrahiert 9 von der Zahl, wenn sie größer als 9 ist. Implementiert als: kopiere die Zahl, vergleiche mit 9, multipliziere das Ergebnis (entweder 0 oder 1) mit 9 und subtrahiere dann. 1 2 6
    4. + fügt das schließlich zur ersten Zahl hinzu. 1 8
  4. +(nach dem if) addiert das Ergebnis von ifzum ursprünglichen Wert und ergibt den neuen gefalteten Wert.

Nachdem die Faltung abgeschlossen ist, modifizieren wir einfach mit 10 ( 10%) und negieren das Ergebnis ( !), so dass wir 1 zurückgeben, wenn die Summe ein Vielfaches von 10 ist.


Dies scheint 0 für die Beispielnummer auf Wikipedia (49927398716)
gnibbler

nm. Ich habe vergessen zu benutzenecho -n
gnibbler

1
@ Gnibbler: Haha, scheitern. :-P (Ernsthaft, ich habe mich bei meinen ersten Tests auch davon gestochen fühlen.)
Chris Jester-Young

1
Ein paar Orte, um ein paar einfache Charaktere hier zu speichern. -1% 2/kombinierbar zu -2/. 1,kann durch ersetzt werden 0(0 wird zu einem Array gezwungen, dann +wird verkettet). 9>9*-kann durch ersetzt werden 9>+(da es sich nur um die letzte Ziffer handelt). Außerdem ist die Überprüfung auf ungerade Längen etwas lang und die Verwendung .,2%,\+ist kürzer. Ändern , nachdem diese Weise können wir auch {16%}%und (\0=in {16}/(innerhalb der Schleife). Sobald Sie alles, was getan haben, wird es in etwa so aussehen: .,2%,\+-2/0\+{{16%}/2*.9>+++}*10%!.
Nabb

@Nabb: Danke! Ich werde diese in meine Lösung einbauen, obwohl es so aussieht, als hättest du bereits eine, die einen ernsthaften Arsch tritt. :-)
Chris Jester-Young

11

Python, 73 69 Zeichen

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

4
Sie können zwei weitere Zeichen sparen, indem Sie nicht rückwärts schleifen: D[-2::-2]-> D[1::2]da die Reihenfolge einer Summe nicht wichtig ist :)
ThinkChaos

==0kann verkürzt werden auf<1
Black Owl Kai

10

Python 3, 77 Bytes

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

9

C # 119 Zeichen:

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

Nicht zu schlecht für einen Code Golf n00b in einer statisch typisierte Sprache, hoffe ich.

Dies kann auf 100 reduziert werden :

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

Es ist eine gute Idee und ein interessanter Ansatz, aber es scheint nicht zu funktionieren. Zumindest nicht bei meinen wenigen Tests. Es sieht so aus, als ob das "i" in Ihrem ersten Lambda der Index des Zeichens in der Zeichenfolge sein soll. Funktioniert das so wie es sollte? Wenn ja, warum kehren Sie die Zeichenfolge nur um, um sie dann basierend auf der Indexposition zu ändern? Scheint ein bisschen überflüssig, nein?
Nellius

Ich habe nur eine meiner Kreditkarten getestet und ein paar Fehler daraus gemacht. TBH. (Mit dem VS 2008-Debugger) Der Algorithmus soll jede zweite Ziffer, beginnend mit der LETZTEN Ziffer, verdoppeln. Wenn ich die Zeichenfolge nicht umkehren würde, wäre dies für Zeichenfolgen mit ungeraden Längen falsch.
Mootinator

Es stellte sich heraus, dass ich das Ergebnis von i%2<1?1:2rückwärts hatte. Vielen Dank.
Mootinator

8

Golfscript - 34 Zeichen

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

Beispielnummer aus Wikipedia Seite 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

Das .+(9%)ist sehr innovativ (für mich jedenfalls). Ich mag! +1
Chris Jester-Young

Allerdings benötigt GolfScript einen Partitionierungsoperator, so dass Sie diesen Unsinn "Drop End Item Off and Repeat" nicht machen müssen. :-)
Chris Jester-Young

1
@ Chris, das habe ich vor vielen Jahren als "Neunen austreiben" erfahren. Es ist eine gute Möglichkeit,
Langzeigeradditionen

3
Dies funktioniert nicht, wenn der Wert 0 verdoppelt wird ( 0(9%)9 und nicht 0).
Nabb

8

PHP, 108 Bytes

<?function v($s,$t=0){for($i=strlen($s);$i>=0;$i--,$c=$s[$i])$t+=$c+$i%2*(($c>4)*-4+$c%5);return!($t % 10);}

7

Ruby - 85 Zeichen

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

Sie wissen wahrscheinlich Bescheid, aber Sie könnten .sum anstelle von .inject (: +) ausführen, um 7 Bytes zu sparen
Håvard Nygård

7

Haskell, 96 Bytes

Es muss einen besseren / kürzeren Weg geben, aber hier ist meine Haskell- Lösung in 96 Zeichen :

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

Leider kann die digitToIntFunktion nur verwendet werden, wenn Sie import Data.Charzuerst. Sonst könnte ich zu 88 Zeichen runter durch den Ersatz ((+(-48)).fromEnum)mit digitToInt.


6

Windows PowerShell, 82

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

Geschichte:

  • 2011-02-13 03:08 (84) Erster Versuch.
  • 2011-02-13 12:13 (82) Ich muss nicht beitreten, da Leerzeichen nicht schaden. +1 + +3kann noch ausgewertet werden.

5

Q, 63

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

Verwendungszweck

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 Bytes mit {0=mod[sum"J"$raze($)($)x*#:[x]#1 2]10}"I"$'(|)einem anderen Weg, um die ungeraden Indizes zu verdoppeln.
Streetster

5

D, 144 Bytes

bool f(S)(S s){int t(C)(C c){return to!int(c)-'0';}int n,v;foreach(i,c;array(retro(s))){v=i&1?t(c)*2:t(c);n+=v>=10?v%10+v/10:v;}return n%10==0;}

Besser leserlich:

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 Bytes

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

Explosionszeichnung

{                     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

Beispiele

      {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 Bytes

Beinhaltet +1 für -p

Geben Sie Input auf STDIN:

luhn.pl <<< 79927398713

luhn.pl:

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

Können Sie bitte erklären, wie das funktioniert? Sie scheinen durch das Match und dann auch durch die Matchzeiten 1.2 zu dekrementieren, aber nur in den richtigen Positionen. Warum 1.2? Sollte es nicht sein $=-=-$&-$&*/\G(..)+$/?
msh210

3
@ msh210: Es ist die Wirkung der Multiplikation kodiert durch 2 0..4* 2 gibt 0, 2, 4, 6, 8aber 5..9gibt 10,12,14,16,18die Summe , 1 3 5 7 9die die gleichen letzten Ziffern wie haben 11 13 15 17 19die die gleichen Werte wie 0..9 * 2.2wenn Sie auf ganzzahlige gestutzt. Der erste trägt $&bereits einen Faktor bei 1, so dass eine Korrektur durch 1.2noch erforderlich ist. $=Kann nur ganze Zahlen enthalten und beginnt mit einem Wert, der auf 0 endet. Die negativen Werte werden benötigt, da sich der /\G/reguläre Ausdruck $&noch auf dem Auswertungsstapel ändert , sodass sie geändert werden müssen
Ton Hospel

Oh. Brillant! Und danke für die Erklärung.
msh210

3

JavaScript (ES6), 61 Byte

Nicht konkurrierend, da JavaScript im Jahr 2011 sehr unterschiedlich war.

Summe der Ziffern von 2*nist 2*nwenn n in 0..4, 2*n-9wenn n in 5..9. Trotzdem kann die gesamte Summe in einem Schritt berechnet werden.

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

3

Jelly , 12 11 Bytes

ṚḤJḤ$¦DFS⁵ḍ

Probieren Sie es online! (mit allen Testfällen)

Wie es funktioniert

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

Alternativ für 12 Bytes:

ṚḤJḤ$¦DFSḍ@⁵

3

8086 Assembly , IBM PC DOS,29 28 25 23 Bytes

; 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

Verwendet (missbraucht) die BCD-zu-Binär-Anweisungen des x86, um die Aufteilung und modulo 10Überprüfung der einzelnen Ziffern zu handhaben . Es stellt sich heraus, dass die Befehle AAMund AADeine BCD / Binär-Konvertierung von Bytewerten durchführen (was sehr praktisch sein kann), obwohl nicht dokumentiert oder beschrieben wird, dass diese Funktion generisch ausgeführt wird.

Für alle offiziellen IBM / MS DOS - Versionen, AXund BXinitialisiert , um 0000beim Start ( ref , ref ) und DXzu CS, was ein Wert ist 12-Bit ist so sein , nicht Null und positiv garantiert. Dies ist , wie wir garantieren können , BXist 0und kann Flip / Flop DXungerade zu bestimmen , / selbst eingegebenen Ziffern Orte.

Beispielausgabe:

Bildbeschreibung hier eingeben

Laden Sie das IBM PC DOS-Testprogramm LUHN.COM herunter .


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

Aufruf:

c("79927398713")
  • reverse ("79927398713") = 31789372997
  • s (0), am Schwanz: (3) (1789372997)
  • Schieben (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 Zeichen

Dies ist eine originelle Lösung, die ich mir ausgedacht habe, bevor ich diesen Beitrag gefunden habe:

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

Lesbare Form:

function luhnCheck(ccNum) {
    return !(                                  // True if the result is zero.
             ccNum.split('').
               reverse().                      // Iterate over the string from rtl.
               reduce(function(prev, cur, idx) {
                 return prev +                 // Sum the results of each character.
                        (+cur &&               // If the current digit is 0, move on.
                         ((cur * (1 + idx % 2) // Double cur at even indices.
                           % 9) || 9));        // Sum the digits of the result.
               }, 0)
            % 10);                             // Is the sum evenly divisible by 10?
}


2

Retina , 43-42 Bytes

Retina ist (viel) neuer als diese Herausforderung.


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

Die führende Leerzeile ist signifikant.

Druck 0für falsy und 1für truthy Ergebnisse.

Probieren Sie es online! (Leicht modifiziert, um alle Testfälle gleichzeitig auszuführen.)

Erläuterung


;

An ;jeder Stelle einfügen , um die Ziffern zu trennen.

r`(.);.
$1$&

Ab dem rZeitpunkt stimmen wir wiederholt mit zwei Ziffern überein und verdoppeln die linke. Auf diese Weise vermeiden wir eine teure Umkehrung der Liste.

\d
$*

Wir passen jede Ziffer an und wandeln sie in so viele 1s um (dh wir wandeln jede Ziffer in eine unäre Zahl um).

1+
$.&

Dies entspricht jeder unären Zahl und konvertiert sie zurück in eine Dezimalzahl, indem sie durch ihre Länge ersetzt wird. Zusammen mit der vorherigen Stufe werden die zweistelligen Ziffern hinzugefügt.

.
$*

Auch hier stimmen wir mit jedem Charakter überein und verwandeln ihn in so viele 1s. Das heißt, wir konvertieren jede Ziffer einzeln zurück in unär. Dies entspricht auch den ;Trennzeichen, die bei der Konvertierung als Nullen behandelt werden, dh sie werden einfach entfernt. Da nun alle unären Zahlen zusammengedrückt sind, haben wir die unären Darstellungen aller Ziffern automatisch addiert.

$
$._

Am Ende fügen wir die Länge des gesamten Strings ein, dh die dezimale Darstellung der unären Prüfsumme.

0$

Zum Schluss zählen wir die Anzahl der Übereinstimmungen dieses Regex, dh wir prüfen, ob die Dezimaldarstellung endet 0, druckt 0oder 1dementsprechend.


2

Powershell, 74 Bytes

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

Erläuterung

  1. für jedes Zeichen eines Argumentstrings in umgekehrter Reihenfolge
  2. Erhalte eine Ziffer mit dem doppelten Wert einer Ziffer
  3. ein doppelter Wert einer Ziffer kann nicht größer als 18 sein. Daher akkumulieren wir einen Wert minus 9, wenn der Wert> 9 ist
  4. Geben Sie true zurück, wenn der Rest der Division durch 10 0 ist

Skript testen

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

Ausgabe

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 Bytes

RSāÈ>*SOTÖ

Probieren Sie es online! oder als Testsuite

Erläuterung

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 Bytes

(einschließlich +1 für die -rFlagge)

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 ist fast nie die natürlichste Sprache für Arithmetik, aber los geht's:

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

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

erwartet die Zahl als Zahl, nicht als Zeichenfolge, aber das liegt nur daran, dass tryAPL (verständlicherweise) nicht implementiert wird

weiter reduzierbar, da bin ich mir sicher ...


1

PHP - 136 Zeichen

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 Bytes (nicht konkurrierend)

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

Probieren Sie es online!

Gibt 1 für eine gültige Zahl aus, sonst 0.

Dank Luis Mendos Vorschlägen wurden drei Bytes eingespart.

Erläuterung

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 Bytes

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

Probieren Sie es online!

Erläuterung:

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

Warum ist das nicht konkurrierend?
Mudkip201

@ mudkip201 Korrigiere mich, wenn ich falsch liege, aber diese Version von Jelly gab es nicht, als die Frage gestellt wurde, daher ist sie für die Frage nicht gültig.
Ellie

3
Ziemlich sicher, dass es einen
Metakonsens
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.