Калькулятор символів управління іспанською карткою


20

Це дуже простий алгоритм, який я впевнений, що його можна вирішити багатьма різними мовами. В Іспанії посвідчення особи (відомі як DNI ) складаються з 8 чисел та контрольного символу. Символ управління обчислюється за наступним алгоритмом: розділіть число на 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 належить іноземному особі , яка проживає в Іспанії, перша цифра змінюється на X, Yабо , Zі це називається NIE . У цьому випадку перед обчисленням контрольного символу здійснюються такі заміни:

X Y Z
0 1 2

В Інтернеті є багато калькуляторів, які допомагають отримати контрольний символ, але, як коротко ви можете написати цей код? Напишіть алгоритм (програму або функцію), який отримує номер stringз DNI (який завжди буде складатися з 8 буквено-цифрових символів) і повертає лише обчислений єдиний символ управління і нічого більше (приймається новий рядок).

Примітки:

  • DNI завжди записується великими літерами, але у алгоритмі ви можете вводити та виводити великі чи малі регістри, просто будьте послідовними.
  • У реальному житті, деякі Нуй , випущені до 2008 року мають 8 цифр після X, Yабо 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, виконайте решту операції", правильний термін залишок ; відпочинок занадто розмовний.
Locoluis

2
@Locoluis іспанською мовою ми говоримо Реста , що робить «відпочинок» помилковий друг, а потім. Принаймні, я не використав неправильний термін. :-) Дякую!
Чарлі

Відповіді:


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 завдяки Джонатану Аллану .


1
Ви можете замінити str('XYZ'.index(n[0]))на str(ord(n[0])-88)і зберегти 5 байт
Алікс Eisenhardt

1
@AlixEisenhardt Наведена вище пропозиція надихнула мене змінити техніку на лямбда, що в підсумку зберегло 10 байт.
Містер Xcoder

Збережіть байт, замінивши -88на %4.
Джонатан Аллан

8

Haskell , 107 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 байт

Код містить кілька недрукованих символів, тому тут є оборотний xxdгекс-дамп.

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 отримує останні три символи алфавіту, "xyz" .
  • U3 отримує асортимент [0, 3 [ ,[0, 1, 2] .
  • Xкарти xyzдо [0, 1, 2]в розділеному масиві, наприклад["y", "0000369"] в [1, "0000369"]. Це замінює перший символ, якщо він є одним ізxyz , а хвіст із 7 символів залишається недоторканим, оскільки жодна рядок із 7 символів не може бути дорівнює одному символу.
  • s приєднується до масиву з порожнім рядком, наприклад [1, "0000369"] до"10000369" .
  • s кидає цей рядок до цілого числа, наприклад "10000369" до 10000369. Це призводить до помилки, якщо в рядку залишаються зайві нецифрові символи.
  • %23Отримує значення модуля 23, напр10000369 до 15.
  • C""Перетворює двійковий рядок з базового 256 в ціле число (приблизно 3,06 × 10) 26 ).
  • .PG Отримує перестановку алфавіту з цим індексом.
  • @ отримує правильний характер від перестановки.

4

MATL , 62 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.

Один байт збережено завдяки Джонатану Аллану.
Ще один байт збережений завдяки Шаггі.


Можливо, збережіть байт, використовуючи, %4а не -88.
Джонатан Аллан

Ви також можете мати можливість скинути 0з нього charCodeAt().
Shaggy

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);}

-9 байт завдяки @ OliverGrégoire .
-41 байт завдяки @ OliverGrégoire знову, взявши дані як char-масив ( char[]).

Якщо вхід недійсний, він або вийде з ладу java.lang.NumberFormatExceptionабоjava.lang.StringIndexOutOfBoundsException .

Пояснення:

Спробуйте тут. (Недійсні тестові випадки оточені пробним уловом, тому він не зупиняється при першій помилці.)

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)-88і t<0?t+40:tзапасні вам байти.
Олів'є Грегоар

1
Нарешті, ви можете повернути код помилки. Просто вирішите , що це 'a'або '0'або будь-який не заголовна буква, і повернутися , що замість того , щоб t/0і лиття все багато char. Таким чином, ви б зберегли 7 байт. Погравши таким чином , ви отримаєте 145 байт.
Олів’є Грегоар

1
@ OlivierGrégoire Дякую! У мене є відчуття, що все-таки можна використовувати інший спосіб перевірки замість .matchesцього регулярного виразу, btw. Але, можливо, я помиляюся.
Kevin Cruijssen

1
Ні, ви абсолютно праві! Це можна зробити так: s->{s[0]-=s[0]<88?0:40;return"TRWAGMYFPDXBNJZSQVHLCKE".charAt(new Integer(new String(s))%23);}всього 94 байти (з sбуттям а 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буде 0, 1або 2. Якщо перший символ не знаходиться в рядку, то aбуде 3. Якщо aменше , ніж 3, ми переходимо з першого символу для рядка а ( 0, 1або 2), в іншому випадку ми включаємо за перший символ (таким чином , ефективно нічого не робити). Цей рядок передається на довгий ( "J"$), який потім mod'd з 23, щоб дати решту. Цей залишок використовується для індексації в таблиці пошуку.

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

Примітки:

" "повертається в сценаріях помилок, це тому, що каст повертає нуль, а індексація в рядок при індексі нуль - порожнє значення. Я можу додати 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

05AB1E , 41 40 39 байт

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

Бере введення в малі регістри (щоб зберегти 1 байт яй )

Спробуйте в Інтернеті!

Друкує вхід на 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

Діалог 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.