スペイン語IDカード制御文字計算機


20

これは非常に単純なアルゴリズムであり、多くの異なる言語で解決できると確信しています。スペインでは、IDカード(DNIとして知られる)は8つの数字と1つの制御文字で構成されています。制御文字は、次のアルゴリズムを使用して計算されます。数値を23で除算し、操作の残りを取得して、この表に従って文字で置き換えます。

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がスペインに住んでいる外国人のものである場合、最初の数字はに変更されXYまたはNIEZと呼ばれます。この場合、制御文字を計算する前に次の置換が行われます。

X Y Z
0 1 2

オンラインで制御文字を取得するのに役立つ計算機はたくさんありますが、そのコードをどれくらい短く書くことができますか?stringDNI番号(常に8文字の英数字で構成される)を受信し、計算された単一の制御文字のみを返し、それ以上何も返さない(末尾の改行が受け入れられる)アルゴリズム(プログラムまたは関数)を記述します。

ノート:

  • DNIは常に大文字で記述されますが、アルゴリズムでは、一貫性を保つために、入力または出力を大文字または小文字に選択できます。
  • 実際には、2008年以前に発行された一部のNIEにはXYまたはの後に8桁Zがありますが、このゲームの目的のために、現在と同様に7桁があると考えることができます。
  • 入力文字列は常に8文字であると考えることができますが、「8桁」形式でも「[XYZ]プラス7桁」形式でもない場合は、(選択した)エラーを返すか、単にスローする必要があります例外。

テストケース:

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>

これはなので、各言語の最短コードが勝つかもしれません!



2
コードが無効な入力に対して特定の動作をすることは本当に重要ですか?通常、ここでの課題はエラー処理を心配する必要はありません。
グレッグマーティン

3
@GregMartin正確に言えば、通常は必要ないので、エラー入力で特定の動作をコードに表示したかっただけです。
チャーリー

「数値を23で除算し、残りの演算を実行する」では、正しい用語は剰余です。残りは口語すぎです。
ロコルイス

2
私たちが言うスペイン語で@Locoluis Restoのを、その後、偽の友人を「休止」すること、。少なくとも、間違った用語を使用していません。:-) ありがとうございました!
チャーリー

回答:


11

Python 3、83バイト

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

オンラインでお試しください!

-5 AlixEinsenhardtに感謝(99から94)。-1 JonathanAllanに感謝します。


1
あなたは置き換えることができますstr('XYZ'.index(n[0]))によってstr(ord(n[0])-88)5バイトと保存
アリックスEisenhardt

1
@AlixEisenhardt上記の提案に触発されて、この手法をラムダに変更し、最終的に10バイトを節約しました。
Xcoder氏17

に置き換え-88てバイトを保存します%4
ジョナサンアラン

8

Haskell107 93 92バイト

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

オンラインでお試しください!


無効な入力の動作は何ですか?
チャーリー

彼らはプログラムをクラッシュさせるでしょう、私は例でそれを追加しました。(実際には誰もキャッチしない例外をスローします)
-bartavelle

1
すべてのテストを実行できるように、例外をキャッチして送信を更新しました。
-bartavelle

5

Pyth、35 34バイト

コードには印刷できない文字が含まれているため、ここに可逆の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

小文字を使用します。

オンラインでお試しください。 テストスイート。

印刷可能バージョン

@.P305777935990456506899534929G%ssXcz]1>3GU3 23

説明

  • cz]1入力を位置1で、たとえば"y0000369"に分割します["y", "0000369"]
  • >3Gアルファベットの最後の3文字を取得し"xyz"ます。
  • U3範囲[0、3 [[0, 1, 2]
  • Xマップxyz[0, 1, 2]分割された配列で、例えば["y", "0000369"][1, "0000369"]。これは、最初の文字がのいずれかである場合に置き換えられますが、xyz7文字の文字列は単一の文字に等しくないため、7文字の末尾は変更されません。
  • s配列を空の文字列、たとえば[1, "0000369"]toに結合し"10000369"ます。
  • s整数にこの文字列をキャストし、例えば"10000369"10000369。文字列に数字以外の余分な文字が残っていると、エラーがスローされます。
  • %... 23例えば、値のモジュロ23を取得10000369します15
  • C""バイナリ文字列を基数256から整数(約3.06×10 26)に変換します。
  • .PGそのインデックスでアルファベットの順列を取得します。
  • @ 順列から正しい文字を取得します。

4

MATL62 59バイト

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

無効な入力のエラーは、A(I): index out of bounds(OctaveでIndex exceeds matrix dimensions実行されているコンパイラ)または(Matlabで実行されているコンパイラ)です。

オンラインでお試しください!

説明

'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バイト

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

アクションで!

大文字のみ、無効な数値のエラーコードはundefinedです。

ジョナサンアランのおかげで1バイト節約できました。
Shaggyのおかげでもう1バイト節約できました。


たぶん使用してバイトを保存する%4のではなく-88
ジョナサンアラン

0からcharCodeAt()もドロップできるはずです。
シャギー

3

Java 8、154 145 104バイト

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

@OliverGrégoireのおかげで-9バイト。入力をchar-array()として受け取ることで、再び@OliverGrégoireに
感謝します。char[]

入力が無効な場合、java.lang.NumberFormatExceptionまたはで失敗しjava.lang.StringIndexOutOfBoundsExceptionます。

説明:

ここで試してみてください。(無効なテストケースはtry-catchに囲まれているため、最初のエラーで停止しません。)

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
|正規表現では必要ありません。また、int t=s.charAt(0)-88t<0?t+40:tあなたのバイトのスペア。
オリビエグレゴワール

1
最後に、エラーコードを返すことができます。それが大文字である'a'か、'0'または大文字でないことを決定し、代わりにt/0それを返し、全体をにキャストしcharます。この方法で7バイト節約できると思います。このようゴルフすると、145バイトが得られます。
オリビエグレゴワール

1
@OlivierGrégoireありがとう!.matchesこの正規表現の代わりに、別の検証方法を使用することはまだ可能だと感じています。しかし、おそらく私は間違っています。
ケビンCruijssen

1
いいえ、あなたは完全に正しいです!これは次のように実行できます。s->{s[0]-=s[0]<88?0:40;return"TRWAGMYFPDXBNJZSQVHLCKE".charAt(new Integer(new String(s))%23);}たった94バイト(saでchar[]):p
オリビエグレゴワール

1
または、検証について完了したい場合:s[0]<88&s[0]>90さらに8バイト。
オリビエグレゴワール



1

q / kdb +、68バイト

溶液:

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

例:

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

説明:

最初の文字が、場合x 0、文字列である"XYZ"、その後aになります01または2。最初の文字が文字列にない場合、にaなります3aが3未満の場合、a(01または2)の文字列の最初の文字を切り替えます。それ以外の場合、最初の文字を切り替えます(したがって、実質的に何もしません)。この文字列はlong("J"$)にキャストされ、mod23で 'dされて残りが得られます。この残りは、ルックアップテーブルにインデックスを付けるために使用されます。

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

ノート:

" "エラーシナリオで返されるのは、キャストがnullを返し、インデックスnullの文字列へのインデックス付けが空の文字であるためです。"!"^エラーが発生したことをより明確にするために、先頭()に4バイトを追加できます。

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

1

JavaScript(ES6)、121バイト

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

さび、206バイト

さびはコードゴルフに適しているとは思わない-_-

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

05AB1E41 40 39バイト

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

入力を小文字にします(1バイトのyayを保存するため)

オンラインでお試しください!

不正な形式の場合、STDERRへの入力を出力します

説明

ć…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バイト

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

これは、オペランドとして文字列を受け入れ、その結果を返す単項演算子です。

FIXMEは入力をチェックしません。適切にゴルフされていません。

使用法:

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

      OP '01234567'
L

      OP '00000010'
X
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.