Spanyol karakter kartu kendali kalkulator


20

Ini adalah algoritma yang sangat sangat sederhana, yang saya yakin dapat diselesaikan dalam banyak bahasa yang berbeda. Di Spanyol kartu ID (dikenal sebagai DNI ) terdiri dari 8 angka dan karakter kontrol. Karakter kontrol dihitung dengan algoritma berikut: bagi angka dengan 23, ambil sisa operasi dan ganti dengan karakter sesuai tabel ini:

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

Jika DNI milik orang asing yang tinggal di Spanyol, digit pertama diubah menjadi X, Yatau Zdan itu disebut NIE . Dalam hal ini, penggantian berikut dilakukan sebelum menghitung karakter kontrol:

X Y Z
0 1 2

Ada banyak kalkulator online yang membantu Anda mendapatkan karakter kontrol, tetapi, seberapa pendek Anda bisa menulis kode itu? Tulis algoritme (program atau fungsi) yang menerima a stringdengan nomor DNI (yang akan selalu terdiri dari 8 karakter alfanumerik) dan mengembalikan hanya karakter kontrol tunggal yang dihitung dan tidak lebih dari itu (baris baru yang tertinggal diterima).

Catatan:

  • DNI selalu ditulis dalam huruf besar, tetapi dalam algoritma Anda, Anda dapat memilih input dan output menjadi huruf besar atau kecil, konsisten saja.
  • Dalam kehidupan nyata, beberapa NIE yang dikeluarkan sebelum 2008 memiliki 8 digit setelah X, Yatau Z, tetapi untuk tujuan permainan ini, Anda dapat menganggap mereka memiliki 7 digit seperti saat ini.
  • Anda dapat mempertimbangkan bahwa string input akan selalu memiliki 8 karakter, tetapi jika mereka tidak dalam format "8 digit" atau format "[XYZ] plus 7 digit", Anda harus mengembalikan kesalahan (pilihan Anda) atau hanya melempar pengecualian.

Kasus uji:

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>

Ini adalah , jadi semoga kode terpendek untuk setiap bahasa menang!



2
Apakah benar-benar penting bahwa kode memiliki perilaku spesifik pada input yang tidak valid? Biasanya tantangan di sini tidak perlu mengkhawatirkan penanganan kesalahan.
— Greg Martin

3
@GregMartin poin saya tepatnya, saya hanya ingin kode untuk menunjukkan beberapa perilaku spesifik pada input kesalahan karena biasanya tidak diperlukan.
— Charlie

Dalam "bagi nomor dengan 23, ambil sisa operasi", istilah yang benar adalah sisa ; sisanya terlalu sehari-hari.
— Locoluis

2
@Locoluis dalam bahasa Spanyol kami katakan resto , menjadikan "istirahat" sebagai teman palsu, kalau begitu. Setidaknya saya tidak menggunakan istilah yang salah. :-) Terima kasih!
— Charlie

Jawaban:


11

Python 3 , 83 byte

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

Cobalah online!

Terima kasih kepada AlixEinsenhardt (dari 99 hingga 94). -1 terima kasih kepada JonathanAllan .


1
Anda dapat mengganti str('XYZ'.index(n[0]))dengan str(ord(n[0])-88)dan menyimpan 5 byte
— Alix Eisenhardt

1
@AlixEisenhardt Saran di atas mengilhami saya untuk mengubah teknik menjadi lambda, yang akhirnya menghemat 10 byte.
— Tn. Xcoder

Simpan satu byte dengan mengganti -88dengan %4.
— Jonathan Allan

8

Haskell , 107 93 92 byte

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

Cobalah online!


Apa perilaku pada input yang tidak valid?
— Charlie

Mereka akan merusak program, saya menambahkan satu dalam contoh. (dalam prakteknya itu melempar pengecualian yang tidak ada yang menangkap)
— bartavelle

1
Saya memperbarui kiriman dengan pengecualian penangkapan, sehingga semua tes bisa dijalankan.
— bartavelle

5

Pyth, 35 34 byte

Kode berisi beberapa karakter yang tidak patut xxddicetak , jadi di sini adalah hexdump yang dapat dibalik.

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

Menggunakan karakter huruf kecil .

Cobalah online. Suite uji.

Versi cetak

@.P305777935990456506899534929G%ssXcz]1>3GU3 23

Penjelasan

  • cz]1membagi input pada posisi 1, misalnya "y0000369"ke ["y", "0000369"].
  • >3Gmendapat 3 karakter terakhir dari alfabet "xyz",.
  • U3mendapat kisaran [0, 3 [ , [0, 1, 2].
  • Xpeta xyzke [0, 1, 2]dalam array pisah, misalnya ["y", "0000369"]ke [1, "0000369"]. Ini menggantikan karakter pertama jika salah satunya xyz, sambil membiarkan ekor 7 karakter tidak tersentuh karena setiap string 7 karakter tidak dapat sama dengan satu karakter.
  • sbergabung dengan array dengan string kosong, misalnya [1, "0000369"]ke "10000369".
  • smelemparkan string ini ke integer, misalnya "10000369"ke 10000369. Ini menimbulkan kesalahan jika karakter non-digit tambahan dibiarkan dalam string.
  • %… 23Mendapatkan nilai modulo 23, misalnya 10000369ke 15.
  • C"… "Mengonversi string biner dari basis 256 ke integer (sekitar 3.06 × 10 26 ).
  • .P... Gmendapatkan permutasi alfabet dengan indeks itu.
  • @ mendapatkan karakter yang benar dari permutasi.

4

MATL , 62 59 byte

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

Kesalahan untuk input yang tidak valid adalah A(I): index out of bounds (kompiler berjalan di Oktaf) atau Index exceeds matrix dimensions(kompiler berjalan di Matlab).

Cobalah online!

Penjelasan

'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 byte

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

Beraksi!

Hanya huruf besar, kode kesalahan untuk nomor yang tidak valid adalah undefined .

Satu byte disimpan berkat Jonathan Allan.
Satu byte lagi tersimpan berkat Shaggy.


Mungkin menyimpan byte menggunakan %4daripada -88.
— Jonathan Allan

Anda harus dapat menjatuhkan 0dari charCodeAt()juga.
— Shaggy

3

Java 8, 154 145 104 byte

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

-9 byte terima kasih kepada @ OliverGrégoire .
-41 byte terima kasih kepada @ OliverGrégoire lagi, dengan mengambil input sebagai char-array ( char[]).

Jika input tidak valid, itu akan gagal dengan a java.lang.NumberFormatExceptionatau java.lang.StringIndexOutOfBoundsException.

Penjelasan:

Coba di sini. (Kasus uji tidak valid dikelilingi oleh try-catch sehingga tidak berhenti pada kesalahan pertama.)

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
Anda tidak perlu |di regex. Juga int t=s.charAt(0)-88& memberikan t<0?t+40:tAnda satu byte.
— Olivier Grégoire

1
Akhirnya, Anda dapat mengembalikan kode kesalahan. Hanya memutuskan bahwa itu 'a'atau '0'huruf apa pun bukan huruf besar, dan kembalikan itu alih-alih t/0dan masukkan seluruh lot ke char. Anda akan menghemat 7 byte dengan cara ini, saya kira. Golf dengan cara ini , Anda mendapatkan 145 byte.
— Olivier Grégoire

1
@ OlivierGrégoire Terima kasih! Saya merasa masih mungkin untuk menggunakan cara yang berbeda untuk memvalidasi alih-alih .matchesdengan regex ini, btw. Tapi mungkin saya salah.
— Kevin Cruijssen

1
Tidak, kamu benar sekali! Ini bisa dilakukan seperti ini: s->{s[0]-=s[0]<88?0:40;return"TRWAGMYFPDXBNJZSQVHLCKE".charAt(new Integer(new String(s))%23);}hanya untuk 94 byte (dengan smenjadi a char[]): p
— Olivier Grégoire

1
Atau jika Anda ingin melengkapi validasi: s[0]<88&s[0]>90untuk 8 byte lebih.
— Olivier Grégoire



1

q / kdb +, 68 byte

Larutan:

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

Contoh:

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

Penjelasan:

Jika karakter pertama x 0,, ada di string "XYZ"maka aakan menjadi 0, 1atau 2. Jika karakter pertama tidak ada dalam string, maka aakan menjadi 3. Jika akurang dari 3, kita mengganti karakter pertama untuk string a ( 0, 1atau 2), kalau tidak kita beralih untuk karakter pertama (sehingga secara efektif tidak melakukan apa-apa). String ini dilemparkan ke panjang ( "J"$), yang kemudian moddengan 23 untuk memberikan sisanya. Sisa ini digunakan untuk mengindeks ke dalam tabel pencarian.

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

Catatan:

" "dikembalikan dalam skenario kesalahan, ini karena para pemain mengembalikan nol, dan pengindeksan ke string di indeks nol adalah char kosong. Saya bisa menambahkan 4 byte di awal ( "!"^) untuk membuatnya lebih jelas bahwa telah terjadi kesalahan:

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 byte

Saya tidak berpikir karat cocok untuk kode golf -_-

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 byte

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

Mengambil input dalam huruf kecil (untuk menghemat 1 byte yay )

Cobalah online!

Mencetak input ke STDERR jika salah format

Penjelasan

ć…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 byte

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

Ini adalah operator monadik yang menerima string karakter sebagai operan dan mengembalikan hasilnya.

FIXME tidak memeriksa inputnya. Ini tidak golf dengan benar.

Pemakaian:

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

      OP '01234567'
L

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