Spanischer Ausweiskontrollzeichenrechner


20

Dies ist ein sehr sehr einfacher Algorithmus, der sicher in vielen verschiedenen Sprachen gelöst werden kann. In Spanien bestehen Ausweise ( DNI ) aus 8 Ziffern und einem Steuerzeichen. Das Steuerzeichen wird mit dem folgenden Algorithmus berechnet: Teilen Sie die Zahl durch 23, nehmen Sie den Rest der Operation und ersetzen Sie sie durch ein Zeichen gemäß dieser Tabelle:

0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22  
T  R  W  A  G  M  Y  F  P  D  X  B  N  J  Z  S  Q  V  H  L  C  K  E

Wenn der DNI einer in Spanien lebenden ausländischen Person gehört, wird die erste Ziffer in geändert X, Yoder, Zund es wird ein NIE genannt . In diesem Fall werden vor der Berechnung des Steuerzeichens folgende Ersetzungen vorgenommen:

X Y Z
0 1 2

Es gibt viele Taschenrechner im Internet, mit denen Sie das Steuerzeichen ermitteln können. Aber wie kurz können Sie diesen Code schreiben? Schreiben Sie einen Algorithmus (Programm oder Funktion), der eine stringmit der DNI-Nummer (die immer aus 8 alphanumerischen Zeichen besteht) erhält und nur das berechnete einzelne Steuerzeichen und nichts weiter zurückgibt (eine abschließende Zeile wird akzeptiert).

Anmerkungen:

  • Der DNI wird immer in Großbuchstaben geschrieben, aber in Ihrem Algorithmus können Sie die Eingabe und Ausgabe als Groß- oder Kleinbuchstaben auswählen, nur konsistent.
  • Im wirklichen Leben, einige vor 2008 ausgestellt NIEs haben 8 Stellen nach dem X, Yoder Zaber für die Zwecke dieses Spiel, können betrachten Sie sie haben 7 Ziffern , wie sie heute haben.
  • Sie können davon ausgehen, dass die Eingabezeichenfolge immer 8 Zeichen hat. Wenn sie jedoch weder das Format "8 Stellen" noch das Format "[XYZ] plus 7 Stellen" aufweist, müssen Sie einen Fehler (Ihrer Wahl) zurückgeben oder einfach werfen eine Ausnahme.

Testfälle:

00000010 -> X (HRM Juan Carlos I's DNI number)
01234567 -> L
98765432 -> M
69696969 -> T
42424242 -> Y
Z5555555 -> W (Z=2)
Y0000369 -> S (Y=1)
A1234567 -> <Error code or exception>
1231XX12 -> <Error code or exception>

Das ist , also kann der kürzeste Code für jede Sprache gewinnen!



2
Ist es wirklich wichtig, dass der Code bei ungültigen Eingaben ein bestimmtes Verhalten aufweist? Normalerweise müssen Sie sich bei diesen Herausforderungen nicht um die Fehlerbehandlung kümmern.
Greg Martin

3
@ GregMartin genau gesagt, ich wollte nur, dass der Code ein bestimmtes Verhalten bei Fehlereingaben zeigt, da dies normalerweise nicht erforderlich ist.
Charlie

In "Teilen Sie die Zahl durch 23, nehmen Sie den Rest der Operation" ist der korrekte Begriff Rest ; Ruhe ist zu umgangssprachlich.
Locoluis

2
@Locoluis auf Spanisch sagen wir resto und machen "rest" dann zu einem falschen Freund. Zumindest habe ich keinen falschen Begriff verwendet. :-) Vielen Dank!
Charlie

Antworten:


11

Python 3 , 83 Bytes

lambda n:'TRWAGMYFPDXBNJZSQVHLCKE'[int([n,str(ord(n[0])%4)+n[1:]][n[0]in'XYZ'])%23]

Probieren Sie es online!

-5 dank AlixEinsenhardt (von 99 bis 94). -1 Danke an JonathanAllan .


1
Sie können str('XYZ'.index(n[0]))durch str(ord(n[0])-88)5 Bytes ersetzen und speichern
Alix Eisenhardt

1
@AlixEisenhardt Der obige Vorschlag hat mich dazu inspiriert, die Technik in ein Lambda umzuwandeln, wodurch letztendlich 10 Bytes eingespart wurden.
Mr. Xcoder

Speichern Sie ein Byte durch den Ersatz -88mit %4.
Jonathan Allan

8

Haskell , 107 93 92 Bytes

c(x:y)="TRWAGMYFPDXBNJZSQVHLCKE"!!mod(read(("X0Y1Z2"!x):y))23
(a:b:c)!x|x==a=b|2>1=c!x
_!x=x

Probieren Sie es online!


Wie verhält es sich bei ungültigen Eingaben?
Charlie

Sie werden das Programm zum Absturz bringen, habe ich im Beispiel hinzugefügt. (in der Praxis wirft es eine Ausnahme, die niemand fängt)
Bartavelle

1
Ich habe die Einreichung mit Ausnahmefang aktualisiert, damit alle Tests ausgeführt werden können.
Bartavelle

5

Pyth, 35 34 Bytes

Der Code enthält einige nicht druckbare Zeichen. Hier ist also ein umkehrbarer xxdHexdump.

00000000: 402e 5043 22fc eeff 1ffc adc7 e614 9451  @.PC"..........Q
00000010: 2247 2573 7358 637a 5d31 3e33 4755 3320  "G%ssXcz]1>3GU3
00000020: 3233                                     23

Verwendet Kleinbuchstaben .

Probieren Sie es online aus. Testsuite.

Druckbare Version

@.P305777935990456506899534929G%ssXcz]1>3GU3 23

Erläuterung

  • cz]1an Position teilt den Eingang 1, zum Beispiel "y0000369"an ["y", "0000369"].
  • >3GRuft die letzten 3 Buchstaben des Alphabets ab "xyz".
  • U3Ruft den Bereich [0, 3 [ , [0, 1, 2].
  • XKarten xyzzu [0, 1, 2]in Split - Array, zum Beispiel ["y", "0000369"]zu [1, "0000369"]. Dies ersetzt das erste Zeichen, wenn es eines von ist xyz, wobei das Ende von 7 Zeichen unberührt bleibt , da eine 7-Zeichen-Zeichenfolge nicht einem einzelnen Zeichen entsprechen kann.
  • stritt in das Array mit dem leeren String, zB [1, "0000369"]auf "10000369".
  • swandelt diesen String in eine Ganzzahl um, zB "10000369"in 10000369. Dies löst einen Fehler aus, wenn in der Zeichenfolge zusätzliche nichtstellige Zeichen verbleiben.
  • %... 23erhält den Wert Modulo 23, zB 10000369an 15.
  • C""Konvertiert die Binärzeichenfolge von der Basis 256 in eine Ganzzahl (ca. 3,06 × 10 26 ).
  • .PGErhält die Permutation des Alphabets mit diesem Index.
  • @ erhält das richtige Zeichen aus der Permutation.

4

MATL , 62 59 Bytes

'RWAGMYFPDXBNJZSQVHLCKET'j'[\dXYZ]\d{7}'XXg'XYZ'I:47+XEU1))

Der Fehler bei ungültiger Eingabe ist A(I): index out of bounds(Compiler läuft in Octave) oder Index exceeds matrix dimensions(Compiler läuft in Matlab).

Probieren Sie es online!

Erläuterung

'RWAGMYFPDXBNJZSQVHLCKET' % Push this string (output letters circularly shifted by 1)
j                         % Unevaluated input
'[\dXYZ]\d{7}'            % Push this string (regexp pattern)
XX                        % Regexp. Returns cell arary with matching string, or empty
g                         % Convert to standard array. Will be empty if non-valid input
'XYZ'                     % Push this string
I:47+                     % Push [47 48 49] (ASCII codes of '012')
XE                        % Transliterate
U                         % Convert to number
1)                        % Get first entry. Gives an error if empty
)                         % Index (modular, 1-based) into initial string
                          % Implicitly display

4

ES6, 83 82 81 Bytes

i=>'TRWAGMYFPDXBNJZSQVHLCKE'[(/^[XYZ]/.test(i)?i.charCodeAt()%4+i.slice(1):i)%23]

In Aktion!

Nur in Großbuchstaben, der Fehlercode für ungültige Nummern lautet undefined.

Ein Byte gespart dank Jonathan Allan.
Ein weiteres Byte wurde dank Shaggy gespeichert.


Vielleicht speichern Sie ein Byte mit %4anstatt -88.
Jonathan Allan

Sie sollten die fallen der Lage sein , 0aus charCodeAt()zu.
Shaggy

3

Java 8, 154 145 104 Bytes

s->{s[0]-=s[0]<88|s[0]>90?0:40;return"TRWAGMYFPDXBNJZSQVHLCKE".charA‌​t(new Integer(new String(s))%23);}

-9 Bytes dank @ OliverGrégoire .
-41 Bytes nochmals dank @ OliverGrégoire , indem die Eingabe als char-array ( char[]) übernommen wird.

Wenn die Eingabe ungültig ist, schlägt sie entweder mit einem java.lang.NumberFormatExceptionoder fehl java.lang.StringIndexOutOfBoundsException.

Erläuterung:

Probieren Sie es hier aus. (Ungültige Testfälle sind von try-catch umgeben, damit sie nicht beim ersten Fehler aufhören.)

s->{                      // Method with char[] parameter and char return-type
  s[0]-=s[0]<88|s[0]>90?  // If the first character is not XYZ:
    0                     //  Leave the first character as is
   :                      // Else:
    40;                   //  Subtract 40 to convert it to 012
  return"TRWAGMYFPDXBNJZSQVHLCKE".charAt(
                          //    Get the char from the String
    new Integer(          //    by converting the following String to an integer:
      new String(s)       //     by converting the char-array to a String
    )%23);                //    And take modulo-23 of that integer
}                         // End of method

1
Du brauchst das nicht |im Regex. Auch int t=s.charAt(0)-88und t<0?t+40:tersparen Sie Ihnen ein Byte.
Olivier Grégoire

1
Schließlich können Sie einen Fehlercode zurückgeben. Entscheide dich einfach, ob es sich um einen 'a'oder '0'einen anderen Großbuchstaben handelt, und gib diesen zurück, anstatt t/0das ganze Los zu werfen char. Sie würden auf diese Weise 7 Bytes sparen, denke ich. Auf diese Weise erhalten Sie 145 Bytes.
Olivier Grégoire

1
@ OlivierGrégoire Danke! Ich habe das Gefühl, dass es immer noch möglich ist, eine andere Art der Validierung zu verwenden als .matchesmit dieser Regex, übrigens. Aber vielleicht irre ich mich.
Kevin Cruijssen

1
Nein, du hast vollkommen recht! Es ist machbar wie folgt: s->{s[0]-=s[0]<88?0:40;return"TRWAGMYFPDXBNJZSQVHLCKE".charAt(new Integer(new String(s))%23);}für nur 94 Bytes (mit sa char[]): p
Olivier Grégoire

1
Oder wenn Sie die Validierung abschließen möchten: s[0]<88&s[0]>90für 8 weitere Bytes.
Olivier Grégoire



1

q / kdb + 68 Bytes

Lösung:

{"TRWAGMYFPDXBNJZSQVHLCKE"mod["J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x;23]}

Beispiele:

q){"TRWAGMYFPDXBNJZSQVHLCKE"mod["J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x;23]}"00000010"
"X"
q){"TRWAGMYFPDXBNJZSQVHLCKE"mod["J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x;23]}"01234567"
"L"
q){"TRWAGMYFPDXBNJZSQVHLCKE"mod["J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x;23]}"98765432"
"M"
q){"TRWAGMYFPDXBNJZSQVHLCKE"mod["J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x;23]}"69696969"
"T"
q){"TRWAGMYFPDXBNJZSQVHLCKE"mod["J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x;23]}"42424242"
"Y"
q){"TRWAGMYFPDXBNJZSQVHLCKE"mod["J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x;23]}"Z5555555"
"W"
q){"TRWAGMYFPDXBNJZSQVHLCKE"mod["J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x;23]}"Y0000369"
"S"
q){"TRWAGMYFPDXBNJZSQVHLCKE"mod["J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x;23]}"A1234567"
" "
q){"TRWAGMYFPDXBNJZSQVHLCKE"mod["J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x;23]}"1231XX12"
" "

Erläuterung:

Wenn das erste Zeichen, x 0in der Zeichenfolge "XYZ"dann awird 0, 1oder 2. Befindet sich das erste Zeichen nicht in der Zeichenfolge, ist dies ader Fall 3. Wenn akleiner als 3 ist, wird das erste Zeichen für die Zeichenfolge von a ( 0, 1oder 2) ausgetauscht, andernfalls wird das erste Zeichen ausgetauscht (was effektiv nichts bewirkt). Diese Zeichenfolge wird in ein long ( "J"$) umgewandelt, das dann modmit 23 angegeben wird, um den Rest zu erhalten. Dieser Rest wird zum Indizieren in die Nachschlagetabelle verwendet.

{ "TRWAGMYFPDXBNJZSQVHLCKE" mod["J"$$[3>a:"XYZ"?x 0;string a;x 0],1_x;23] } / ungolfed solution
{                                                                         } / lambda function
                            mod[                                     ;23]   / performds mod 23 of the stuff in the gap
                                                                  1_x       / 1 drop input, drops the first character
                                                                 ,          / concatenation
                                    $[             ;        ;   ]           / if COND then TRUE else FALSE - $[COND;TRUE;FALSE]
                                        a:"XYZ"?x 0                         / "XYZ" find x[0], save result in a
                                      3>                                    / is this result smaller than 3
                                                    string a                / if so, then string a, e.g. 0 -> "0"
                                                             x 0            / if not, just return first character x[0]
                                "J"$                                        / cast to long
  "TRWAGMYFPDXBNJZSQVHLCKE"                                                 / the lookup table

Anmerkungen:

" "wird in den Fehlerszenarien zurückgegeben, da die Umwandlung eine Null zurückgibt und die Indizierung in eine Zeichenfolge bei Index Null ein leeres Zeichen ist. Ich könnte am Anfang 4 Bytes hinzufügen ( "!"^), um klarer zu machen, dass ein Fehler aufgetreten ist:

q){"!"^"TRWAGMYFPDXBNJZSQVHLCKE"("J"$$[3>a:"XYZ"?x 0;($)a;x 0],1_x)mod 23}"1231XX12"
"!"

1

JavaScript (ES6), 121 Byte

f=i=>{c=+i[0];a=3;while(a--){i[0]=="XYZ"[a]&&(c=a)}b=7;while(b--){c= +i[7-b]+c*10}return "TRWAGMYFPDXBNJZSQVHLCKE"[c%23]}

console.log([f("00000010"),f("01234567"),f("98765432"),f("69696969"),f("42424242"),f("Z5555555"),f("Y0000369"),f("A1234567"),f("1231XX12")])



1

Rust, 206 Bytes

Ich denke nicht, dass Rost gut zum Code-Golfen geeignet ist -_-

let b=|s:&str|{s.chars().enumerate().map(|(i,c)|match i{0=>match c{'X'=>'0','Y'=>'1','Z'=>'2',_=>c},_=>c}).collect::<String>().parse::<usize>().ok().and_then(|x|"TRWAGMYFPDXBNJZSQVHLCKE".chars().nth(x%23))};

1

05AB1E , 41 40 39 Bytes

ć…xyz2ÝJ‡ìDd_i.ǝ}23%.•Xk¦fΣT(:ˆ.Îðv5•sè

Nimmt die Eingabe in Klein (speichern 1 Byte yay )

Probieren Sie es online!

Druckt die Eingabe in STDERR, wenn sie fehlerhaft ist

Erläuterung

ć…xyz2ÝJ‡ìDd_i.ǝ}23%.•Xk¦fΣT(:ˆ.Îðv5•sè
ć                                       # Get head of input and put the rest of the input under it on the stack
 …xyz                                   # Push xyz
     2ÝJ                                # Push 012
        ‡                               # Transliterate
         ì                              # Prepend to the rest of the input
          Dd_                           # Does the result contain something other than numbers?
             i.ǝ}                       # If so print input to STDERR
                 23%                    # Modulo 23
                    .•Xk¦fΣT(:ˆ.Îðv5•   # Pushes the character list
                                     sè # Get the char at the index of the modulo

0

Dyalog APL, 95 Bytes

{'TRWAGMYFPDXBNJZSQVHLCKE'[1+23|(10⊥¯1+'0123456789'⍳{(⍕{('XYZ'⍳⍵)<4:('XYZ'⍳⍵)-1⋄⍵} ⊃⍵),1↓⍵}⍵)]}

Dies ist ein monadischer Operator, der eine Zeichenfolge als Operanden akzeptiert und dessen Ergebnis zurückgibt.

FIXME überprüft seine Eingabe nicht. Es ist nicht richtig golfen.

Verwendung:

    OP ← {'TRWAGMYFPDXBNJZSQVHLCKE'[1+23|(10⊥¯1+'0123456789'⍳{(⍕{('XYZ'⍳⍵)<4:('XYZ'⍳⍵)-1⋄⍵} ⊃⍵),1↓⍵}⍵)]}

      OP '01234567'
L

      OP '00000010'
X
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.