İspanyol kimlik kartı kontrol karakter hesap makinesi


20

Bu çok basit bir algoritma, eminim ki birçok farklı dilde çözülebilir. İspanya'da kimlik kartları ( DNI olarak bilinir ) 8 sayı ve bir kontrol karakterinden oluşur. Kontrol karakteri aşağıdaki algoritma ile hesaplanır: sayıyı 23'e bölün, işlemin geri kalanını alın ve bu tabloya göre bir karakterle değiştirin:

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

DNI İspanya'da yaşayan bir yabancı kişiye aitse, ilk basamak olarak değiştirilir X, Yya Zve bir denir NIE . Bu durumda, kontrol karakteri hesaplanmadan önce aşağıdaki ikameler yapılır:

X Y Z
0 1 2

Kontrol karakterini almanıza yardımcı olan çok sayıda çevrimiçi hesap makinesi var, ancak bu kodu ne kadar kısa yazabilirsiniz? stringDNI numarasıyla (her zaman 8 alfasayısal karakterden oluşacaktır) alan ve yalnızca hesaplanan tek kontrol karakterini döndüren ve daha fazla bir şey olmayan (sondaki yeni satır kabul edilir) bir algoritma (program veya işlev) yazın .

Notlar:

  • DNI her zaman büyük harfle yazılır, ancak algoritmanızda giriş ve çıkışı büyük veya küçük harf olarak seçebilirsiniz, tutarlı olun.
  • Gerçek hayatta, 2008'den önce yayınlanan bazı NIE'lerin X, Yya da Zoyundan sonra 8 hane vardır , ancak bu oyunun amaçları için, günümüzde olduğu gibi 7 hane olduğunu düşünebilirsiniz.
  • Giriş dizesinin her zaman 8 karakter olacağını düşünebilirsiniz, ancak "8 basamak" biçiminde veya "[XYZ] artı 7 basamak" biçiminde değilse, bir hata döndürmeniz (seçtiğiniz) veya sadece atmanız gerekir. bir istisna.

Test senaryoları:

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>

Bu , bu yüzden her dil için en kısa kod kazanabilir!



2
Kodun geçersiz girdide belirli bir davranışı olması gerçekten önemli mi? Genellikle buradaki zorluklar hata işleme konusunda endişelenmenizi gerektirmez.
Greg Martin

3
@GregMartin benim açımdan tam olarak, kodun genellikle gerekli olmadığı için hata girişlerinde bazı belirli davranışlar göstermesini istedim.
Charlie

“Sayıyı 23'e böl, operasyonun geri kalanını al ” bölümünde doğru terim kalmıştır ; dinlenme çok konuşma diline özgüdür.
Locoluis

2
@Locoluis biz resto diyoruz , o zaman "dinlenme" yanlış bir arkadaş yapmak. En azından yanlış bir terim kullanmadım. :-) Teşekkür ederim!
Charlie

Yanıtlar:


11

Python 3 , 83 bayt

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

Çevrimiçi deneyin!

-5 Teşekkürler AlixEinsenhardt (99'dan 94'e). -1 sayesinde JonathanAllan .


1
Sen yerini alabilir str('XYZ'.index(n[0]))tarafından str(ord(n[0])-88)5 bayt ve kaydedin
Alix Eisenhardt

1
@AlixEisenhardt Yukarıdaki öneri tekniği sonunda lambte olarak değiştirmeme ilham verdi ve sonunda 10 bayt kurtardı.
Bay Xcoder

Değiştirerek byte tasarruf -88ile %4.
Jonathan Allan

8

Haskell , 107 93 92 bayt

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

Çevrimiçi deneyin!


Geçersiz girdilerdeki davranış nedir?
Charlie

Programı çökertecekler, örnekte bir tane ekledim. (pratikte kimsenin yakalamadığı bir istisna atar)
bartavelle

1
Tüm testleri çalıştırmak için gönderimi istisna yakalama ile güncelledim.
bartavelle

5

Pyth, 35 34 bayt

Kod yazdırılamayan bazı karakterler içeriyor, bu yüzden burada tersinir bir xxdhexdump var.

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

Küçük harfler kullanır .

Çevrimiçi deneyin. Test odası.

Basılabilir versiyon

@.P305777935990456506899534929G%ssXcz]1>3GU3 23

açıklama

  • cz]1örneğin pozisyon 1, en giriş böler "y0000369"için ["y", "0000369"].
  • >3GAlfabenin son 3 karakterini alır "xyz".
  • U3[0, 3 [ , aralığını alır [0, 1, 2].
  • Xharitalar xyziçin [0, 1, 2]bölünmüş dizide, mesela ["y", "0000369"]etmek [1, "0000369"]. Bu, eğer varsa xyz7 karakterin kuyruğuna dokunmadan bırakılırsa , ilk karakterin yerine geçer .
  • sörneğin Boş dize ile diziyi katılır [1, "0000369"]için "10000369".
  • stamsayıya bu dizeyi, örneğin atmalarını "10000369"için 10000369. Dizede fazladan basamaksız karakterler bırakılırsa bu bir hata atar.
  • %... 23değer modulo 23 örn alır 10000369için 15.
  • C""İkili dizgiyi taban 256'dan tamsayıya dönüştürür (yaklaşık 3.06 × 10 26 ).
  • .PGBu indeksle alfabenin permütasyonunu alır.
  • @ permütasyondan doğru karakteri alır.

4

MATL , 62 59 bayt

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

Geçerli olmayan giriş için hata A(I): index out of bounds(Octave'de çalışan derleyici) veya Index exceeds matrix dimensions(Matlab'da çalışan derleyici).

Çevrimiçi deneyin!

açıklama

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

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

Eylem!

Yalnızca büyük harf, geçersiz sayılar için hata kodu undefined.

Jonathan Allan sayesinde bir bayt kurtardı.
Shaggy sayesinde bir bayt daha kurtardı.


Belki de %4yerine bir bayt kaydedin -88.
Jonathan Allan

Sen düşmesi gerekir 0dan charCodeAt()da.
Shaggy

3

Java 8, 154 145 104 bayt

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

@ OliverGrégoire sayesinde -9 bayt . @ OliverGrégoire
sayesinde -41 bayt tekrar, char-array ( ) olarak girdi alarak .char[]

Giriş geçersizse, a java.lang.NumberFormatExceptionveya ile başarısız olur java.lang.StringIndexOutOfBoundsException.

Açıklama:

Burada deneyin. (Geçersiz test senaryoları try-catch ile çevrilidir, bu nedenle ilk hatada durmaz.)

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
|Normal ifadeye ihtiyacınız yok . Ayrıca int t=s.charAt(0)-88& t<0?t+40:tsize bir bayt yedek.
Olivier Grégoire

1
Son olarak, bir hata kodu döndürebilirsiniz. Sadece bu kadar karar 'a'veya '0'veya herhangi olmayan büyük harf ve yerine o dönmek t/0ve sürü döküm char. Bu şekilde 7 bayt tasarruf edersiniz, sanırım. Bu şekilde golf oynadığınızda 145 bayt alıyorsunuz.
Olivier Grégoire

1
@ OlivierGrégoire Teşekkürler! .matchesBu normal ifade yerine , btw yerine farklı bir onaylama yöntemi kullanmak mümkün . Ama belki yanılıyorum.
Kevin Cruijssen

1
Hayır, tamamen haklısın! Şu şekilde yapılabilir: s->{s[0]-=s[0]<88?0:40;return"TRWAGMYFPDXBNJZSQVHLCKE".charAt(new Integer(new String(s))%23);}sadece 94 bayt için (bir svarlık ile char[]): p
Olivier Grégoire

1
Veya doğrulama hakkında eksiksiz olmak istiyorsanız: s[0]<88&s[0]>908 bayt daha.
Olivier Grégoire



1

q / kdb +, 68 bayt

Çözüm:

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

Örnekler:

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

Açıklama:

İlk karakter, varsa x 0, dizede olduğu "XYZ"daha sonra aolacak 0, 1ya da 2. İlk karakter dizede değilse a, olur 3. Eğer a3 den az, biz olan metin için ilk karakteri dışarı geçiş bir ( 0, 1ya da 2), aksi takdirde biz ilk karakter (böylece etkili bir şekilde hiçbir şey yapmadan) için dışarı geçin. Bu dize, kalanını vermek için 23 ile birlikte "J"$olan bir long ( ) öğesine dökülür mod. Bu geri kalanı arama tablosuna dizine eklemek için kullanılır.

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

Notlar:

" "hata senaryolarında döndürülürse, bunun nedeni kadronun null değerini döndürmesi ve null dizinindeki bir dizeye dizine eklemenin boş bir karakter olmasıdır. "!"^Bir hatanın meydana geldiğini daha açık hale getirmek için başlangıçta ( ) 4 bayt ekleyebilirim :

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

1

JavaScript (ES6), 121 bayt

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

Pas, 206 bayt

Pasın kod golfü için çok uygun olduğunu sanmıyorum -_-

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 bayt

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

Girişi küçük harflerle alır (1 bayt yay kaydetmek için )

Çevrimiçi deneyin!

Girdiyi hatalı biçimlendirilmişse STDERR'a yazdırır

açıklama

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

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

Bu, karakter dizesini işlenen olarak kabul eden ve sonucunu döndüren monadik bir operatördür.

FIXME girişini kontrol etmez. Düzgün golf değil.

Kullanımı:

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

      OP '01234567'
L

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