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!

Charlie
sumber
Kotak pasir .
Charlie
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 .

Tuan Xcoder
sumber
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!

bartavelle
sumber
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.
PurkkaKoodari
sumber
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
Luis Mendo
sumber
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.

2ndAttmt
sumber
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
Kevin Cruijssen
sumber
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
2

PHP , 88 byte

mencetak 1 untuk suatu kesalahan

$a[0]=strtr(($a=$argn)[0],ZYX,210);echo!ctype_digit($a)?:TRWAGMYFPDXBNJZSQVHLCKE[$a%23];

Cobalah online!

Jörg Hülsermann
sumber
2

Jelly , 42 byte

“X0Y1Z2”⁸y@1¦RṪ€V%23ị“Ñ×ⱮEɼiʋ}'uƒẹsø’ṃØA$¤

Cobalah online!

Terlalu lama, Jelly! Dennis kecewa padamu! [rujukan?]

Erik the Outgolfer
sumber
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"
"!"
streetster
sumber
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")])

Евгений Новиков
sumber
1

Japt , 50 byte

Mirip dengan sebagian besar pendekatan lain.

Input dan output adalah huruf kecil, output undefineduntuk input yang tidak valid.

`tr°gmyfpdxbnjzsqvhlcke`g("xyz"øUg)?Uc %4+UÅ:U %23

Uji itu
Uji semua kasus uji yang valid

Shaggy
sumber
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))};
dgel
sumber
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
Datboi
sumber
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
Locoluis
sumber