Разбор и обработка ввода на языке ключей

9

Давайте разберем и обработаем Key-Language! Учитывая ввод последовательности нажатий клавиш клавиатуры и / или специальных клавиш, напишите программу, функцию и т. Д., Которые выводят продукт, когда все действия обрабатываются на основе следующей клавиатуры:

+-------------------------------------------------------+
| ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | - | + |   |
| ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | _ | = |Del|
+-------------------------------------------------------+
|TAB| q | w | e | r | t | y | u | i | o | p | [ | ] | \ |
|   | Q | W | E | R | T | Y | U | I | O | P | { | } | | |
+-------------------------------------------------------+
|CAPS | a | s | d | f | g | h | j | k | l | ; | ' | RET |
|     | A | S | D | F | G | H | J | K | L | : | " |     |
+-------------------------------------------------------+
| SHIFT | z | x | c | v | b | n | m | , | . | / | SHIFT |
|       | Z | X | C | V | B | N | M | < | > | ? |       |
+-------------------------------------------------------+
|                                                       |
|                      SPACEBAR                         |
+-------------------------------------------------------+                         

Клавиши, которые выводят действительные символы, не состоящие из пробелов, и которые могут быть изменены другими клавишами, будут называться «символьными клавишами», а те, которые изменяют вывод других клавиш или пробелов, будут называться «специальными клавишами». Клавиши алфавита символов, которые будут показаны на входе с прописными буквами, могут быть изменены либо Shiftили Caps Lockк продукции заглавных букв, а остальные клавиши символов может быть изменены только с Shiftпроизводить свои альтернативные символы. Следовательно, Aна входе соответствует a Aсимвольная клавиша, чей обычный вывод aи модифицированный вывод, который можно получить с помощью клавиши Shiftили Caps Lock, есть A. С другой стороны,/, который соответствует / ?символьной клавише, имеет нормальный выходной сигнал /и модифицированный выходной сигнал, который ?можно получить только с Shiftэтим временем.

правила

  • Ввод всегда будет строкой, состоящей из последовательности символьных клавиш и специальных клавиш. Полный специальный ключ для сопоставления строк для ввода (т. Е. Формат, в котором они гарантированно находятся во входе) и их соответствующие действия / выходы заключаются в следующем:

    • <DEL> -> Delete the previous character (including whitespace). If called when string is empty, nothing happens. If called 2 or more times in a row, 2 consecutive deletes happen. For instance, "RE<DEL><DEL>" should return an empty string ("") and also "R<RET><DEL><DEL>E" should return just "E".
    • <CAPS> -> Enable Caps Lock until <CAPS> appears again, upon which it is disabled, although it is not guaranteed to be disabled by the end of the input. Enabling this only modifies the upcoming alphabet keys resulting in them outputting only uppercase letters. For instance, "<CAPS>RE<CAPS>" results in the output "RE", but <CAPS>.<CAPS> would still result in a ".".
    • <RET> -> Add a new line.
    • <SPC> -> Add a single blank space.
    • <TAB> -> Add 4 spaces.
    • <SHFT> -> Shift is held down resulting in the alternate character of the upcoming keypress to be output, after which the key is released. For instance, "<SHFT>A" results in the output "A", "<SHFT>1" results in the output "!", and "<SHFT>1234" results in the output "!234" as only the first upcoming keypress is modified and nothing else. It is guaranteed that a character key will succeed a <SHFT>. Therefore, <SHFT><SPC> is not a possible input.
  • Пустая строка также возможна в качестве входных данных, для которых выходные данные должны быть ничем.

  • Использование любых встроенных программ, которые решают эту проблему напрямую, запрещено.
  • Использование стандартных лазеек запрещено.

Тестовые случаи

Представлено в формате с Actual String Input -> Actual String Outputпоследующим объяснением для немногих.

  1. 1<SHFT>2<TAB><CAPS>R.KAP.<SPC><SHFT>123 -> 1@ R.KAP. !23

    Вывод, 1когда 1клавиша нажата без переключателя, затем удерживается Shift и 2клавиша нажимается, что приводит к @выводу. Затем клавиша Shift отпускается и нажимается Tab, что приводит к отступу в 4 интервала. Следуя, Колпачки нажатии на клавишу блокировки, после чего R, ., K, A, P, и .клавиши нажаты, в результате чего на выходе R.KAP.. И, наконец, одно выходное пространство с последующим смещением в результате !23выводимого , когда 1, 2и 3клавиши нажаты в конце.

  2. <SHFT>ABCDEFG<SHFT>HIJK<SHFT>1<SHFT>2<SHFT>3<SHFT>4567890 -> AbcdefgHijk!@#$567890

    Клавиша «Shift» удерживается нажатой, а затем Aклавиша, что приводит к выводу с Aпоследующим выводом bcdefgпри B-Gнажатии клавиш. Затем клавиша переключения удерживается в нажатом положении снова сменила Hключ, после чего выхода есть H, а затем , ijkкогда I-Kклавиши нажаты. Наконец, все 1-4клавиши изменяются по мере того, как нажатие клавиши shift удерживается перед каждым нажатием клавиши, в результате чего вывод !@#$завершается 567890после 5-0повторного нажатия клавиш.

  3. <CAPS>THIS<SPC>IS<SPC>IN<SPC>ALL<SPC>CAPS<CAPS><SPC>NOW<SPC>THIS<SPC>IS<SPC>IN<SPC>ALL<SPC>LOWERCASE -> THIS IS IN ALL CAPS now this is in all lowercase

  4. <TAB><SPC><TAB><SHFT>1 -> !
  5. <CAPS>WWW<CAPS>.CODEGOLF.STACKEXCHANGE<SHFT>.COM -> WWW.codegolf.stackexchange>com
  6. PROGRAMMING<CAPS><SPC>IS<SPC><CAPS>AWESOME -> programming IS awesome
  7. <DEL><RET><DEL><RET><DEL> -> "" (Empty String)

    Клавиша удаления нажимается в начале, после чего ничего не происходит. Затем нажимается клавиша возврата, в результате чего появляется новая строка, которая удаляется после повторного нажатия клавиши возврата. Наконец, та же самая последовательность (новая строка, сопровождаемая backspace) повторяется. После всего этого на выходе получается пустая строка.

  8. <SHFT>HI<SPC>HOW<SPC>ARE<SPC>YOU<SHFT>/<RET><SHFT>I<SPC><SHFT>AM<SPC>O<DEL><SHFT>GOOD<SHFT>1 -> Hi how are you?\nI Am Good!

  9. <SHFT>,<CAPS>RET<CAPS><SHFT>. -> <RET>

    Строка <RET>должна быть фактической строкой вывода. Таким образом, это не должно выводить новую строку.

  10. <CAPS>67890,.;'[]<CAPS> -> 67890,.;'[]

  11. <CAPS><SHFT>A -> A
  12. RE<DEL><DEL> -> "" (Empty String)
  13. U<RET><DEL><DEL>I -> i
  14. <DEL><DEL><DEL>5<DEL> -> "" (Empty string)
  15. "" (Empty String) -> "" (Empty String)

Это поэтому выигрывает самый короткий код в байтах!

Р. Кап
источник
5
Это странный ключ удаления, который у вас есть ...
Деннис
1
@Dennis Ну, я описываю клавиши на основе клавиатуры моего MacBook Pro, где клавиша удаления удаляет предыдущий символ. Я все еще согласен с вами, хотя. Это довольно странный макет.
Р. Кап
Ах, это объясняет это. Он называется Backspace буквально на каждой клавиатуре, которой я когда-либо владел. бормотает что-то о нормальных нажатиях клавиш клавиатуры
Деннис
1
В тесте № 2 должен быть результат AbcdefgHijk!@#$567890? Кроме того, в тесте № 8 <SHFT>находится в конце строки, но правила гласят: «Гарантируется, что символьная клавиша будет следовать за <SHFT>».
атласолог
@atlasologist Да, вы правы, и приятно ловить! Я забыл обновить те.
Р. Кап

Ответы:

6

16-битный машинный код x86, 140 139 байт

Сохраняется 1 байт, заменяя DL на DX в последнем опкоде. Также исправлены смещения прыжка при разборке, чтобы соответствовать шестнадцатеричному дампу.

Поскольку характер задачи требует некоторых предварительно инициализированных данных, и ответом является не полная программа, а функция, я предполагаю, что в программе есть раздел данных, и компоновщик оперативно обновляет адрес данных. Заполнитель адреса обозначается как «????».

Это шестнадцатеричное представление кода. Параметры - указатель на входную строку в SI и указатель на выходной буфер в DI. Предполагается, что строки имеют нулевое окончание.

8D1E????89F931D231C0FCAC84C07419D0EA72173C3C74263C41720A3C5A770684F675020C20AAEBE2AAC33C41720B3C5A76F324170402D7EBEC2C27EBF94646AC46240F74154848741748741948741A4848741A39F973B34FEBB04680F601EBAAB020AAAAAAB020EBBCB00AEBB84642EB99

Содержимое таблицы сопоставления (25 байт):

"   =<_>?)!@#$%^&*( :{}|`

Количество байтов учитывает как код, так и данные.

Разборка:

8d 1e ?? ??        lea    bx,ds:???? ;Load address of mapping table to BX
89 f9              mov    cx,di      ;Save pointer to output buffer in CX
31 d2              xor    dx,dx      ;DX is the status register, bit 0 - shift status
31 c0              xor    ax,ax      ;bit 8 - caps lock status
fc                 cld               ;Clear DF

_loop:
ac                 lodsb             ;Fetch next char
84 c0              test   al,al      ;If end of string found
74 19              je     _end       ;break
d0 ea              shr    dl,1       ;Copy shift flag to CF and clear it
72 17              jc     _shift     ;Branch to input procssing with shift set
3c 3c              cmp    al,0x3c    ;If AL == '<'
74 26              je     _special   ;branch to special character processing
3c 41              cmp    al,0x41    ;At this point anything
72 0a              jb     _out       ;not in 'A'..'Z' range
3c 5a              cmp    al,0x5a    ;should be printed unmodified
77 06              ja     _out
84 f6              test   dh,dh      ;If caps lock status flag is set
75 02              jne    _out       ;go to printing right away
0c 20              or     al,0x20    ;otherwise convert to lower case
_out:
aa                 stosb             ;Store AL into output buffer
eb e2              jmp    _loop      ;Continue
_end:
aa                 stosb             ;NULL-terminate the output string
c3                 ret               ;and return

_shift:
3c 41              cmp    al,0x41    ;AL in the range [0x27..0x3b] with
72 0b              jb     _xlat0     ;a couple of holes in it

3c 5a              cmp    al,0x5a    ;AL in the range 'A'..'Z'
76 f3              jbe    _out       ;Since shift is active, go print it

24 17              and    al,0x17    ;AL is 0x5b, 0x5c, 0x5d or 0x7e,
04 02              add    al,0x2     ;convert to the [0x15..0x18] range
_xlat:
d7                 xlatb             ;Lookup mapping table (AL=[BX+AL])
eb ec              jmp    _out
_xlat0:
2c 27              sub    al,0x27    ;Convert AL to be a zero-based index
eb f9              jmp    _xlat      ;Reuse lookup code

_special:                            ;The next 4 or 5 chars are special character opcode
46                 inc    si         ;Since correct input format is guaranteed
46                 inc    si         ;don't bother reading & checking all of them,
ac                 lodsb             ;just load the third one and skip the rest
46                 inc    si         ;The lower 4 bits of the 3rd char
24 0f              and    al,0xf     ;allow to differentiate opcodes

74 15              jz     _sc_caps   ;0x0
48                 dec    ax
48                 dec    ax
74 17              jz     _sc_tab    ;0x2
48                 dec    ax
74 19              jz     _sc_spc    ;0x3
48                 dec    ax
74 1a              jz     _sc_ret    ;0x4
48                 dec    ax
48                 dec    ax
74 1a              jz     _sc_shft   ;0x6

_sc_del:                             ;0xC, <DEL> opcode
39 f9              cmp    cx,di      ;Check the length of the current output
73 b3              jae    _loop      ;DI <= CX ==> NOOP
4f                 dec    di         ;Remove the last char
eb b0              jmp    _loop
_sc_caps:                            ;<CAPS> opcode
46                 inc    si         ;Consume leftover '>' from the input
80 f6 01           xor    dh,0x1     ;Flip caps lock status bit
eb aa              jmp    _loop
_sc_tab:                             ;<TAB> opcode
b0 20              mov    al,0x20    ;Space char
aa                 stosb             ;Print it three times
aa                 stosb             ;and let the <SPC> handler
aa                 stosb             ;do the last one
_sc_spc:                             ;<SPC> opcode
b0 20              mov    al,0x20    ;Space char
eb bc              jmp    _out       ;Go print it
_sc_ret:                             ;<RET> opcode
b0 0a              mov    al,0xa     ;Newline char
eb b8              jmp    _out       ;Go print it
_sc_shft:                            ;<SHFT> opcode
46                 inc    si         ;Consume leftover '>' from the input
42                 inc    dx         ;Set shift status bit (DL is guaranteed to be zero)
eb 99              jmp    _loop

Для набора 32-битных команд код абсолютно одинаков, за исключением первой инструкции, которая длиннее на 2 байта из-за 32-битной адресации (8d1d ???????? lea ebx, ds: ??????? ?)

Зорница
источник
Хорошо сделано! :) Если это не так уж и сложно, не могли бы вы проверить, возвращается ли ваша программа и выводит ли она iдля теста U<RET><DEL><DEL>Iи пустую строку для ввода RE<DEL><DEL>? Я немного разъяснил правила, касающиеся ключа удаления, поэтому, если эти 2 контрольных примера не работают, не могли бы вы также обновить свой код, чтобы он выдавал правильный вывод для этих контрольных примеров? Спасибо!
Р. Кап
Все тесты успешно пройдены. Почему <DEL> работает неправильно? Это просто уменьшение регистра с проверкой границ
меден
Все в порядке. Я просто хотел убедиться, что ваша программа работает как надо. Отличный ответ.
Р. Кап
Нам нужно больше особых случаев. Было бы более интересно, если бы <DEL> не смог удалить <RET>. Я могу реализовать это всего за 3 байта.
Меден
1
При вводе в командной строке оболочки это имеет смысл. Но, заметьте, я не прошу об изменении правила. Спасибо за вызов.
Меден
4

Сетчатка, 136 байт

Вероятно, можно играть в гольф дальше.

<SHFT>
§
<SPC>

<TAB>

<CAPS>
¶
<RET>
þ
<DEL>
÷
T`L`l` (? <= ^ (. * ¶. * ¶) *). +
T` - =; '[] / \\ ,. w` \ _ +: "{} | <> _) @ # $% ^ & * (lL`§?!.
§ | ¶

я ( `þ
¶
[^ §]? ÷

Проверьте все тестовые случаи. (Немного изменен, чтобы запускать все тестовые сценарии одновременно.)

Дрянная Монахиня
источник
Caps + Shift + A = a на моей клавиатуре.
Нил
@Neil Ну, для целей этой задачи (и в соответствии с клавиатурой моего Macbook Pro) Caps+Shift+A = A. Человек моя клавиатура странно ...
Р. Кап
CAPS + SHIFT + A = A. С какой стати заглавные буквы инвертируются?
кот
1
@ cat в миллионах в системе Windows CAPS Invert Shift, независимо от того, сколько знаков вопроса вы пишете. Потому что это удобно и пользователи к этому
привыкли
1
А-а-а, два 110-байтовых решения: retina.tryitonline.net/… , retina.tryitonline.net/… ... Я думаю, что я уже закончил. ;)
Мартин Эндер
4

JavaScript (ES6), 207

Обновлен, чтобы исправить ошибку с повторным удалением, даже на несколько байт короче.

s=>s.replace(/<\w+>|./g,x=>(k=x[3])=='L'?o=o.slice(0,-1):k=='P'?l=!l:k=='F'?s=0:o+=k?k<'C'?'    ':k<'D'?' ':`
`:s?l?x.toLowerCase():x:s=")!@#$%^&*("[x]||'_={}|:"<>?'["-+[]\\;',./".indexOf(x)]||x,l=s,o='')&&o

меньше гольфа

s=>s.replace( /<\w+>|./g, x =>
  (k=x[3]) == 'L' ? o = o.slice(0,-1)
  : k == 'P' ? l = !l
  : k == 'F' ? s = 0
  : o+= k ? k < 'C' ? '    ' : k < 'D' ? ' ' : '\n'
  : s ? l ? x.toLowerCase() : x
  : s = ")!@#$%^&*("[x] || '_={}|:"<>?' ["-+[]\\;',./".indexOf(x)] || x,
  l = s, o = ''
) && o

Тестовое задание

F=
s=>s.replace(/<\w+>|./g,x=>(k=x[3])=='L'?o=o.slice(0,-1):k=='P'?l=!l:k=='F'?s=0:o+=k?k<'C'?'    ':k<'D'?' ':`
`:s?l?x.toLowerCase():x:s=")!@#$%^&*("[x]||'_={}|:"<>?'["-+[]\\;',./".indexOf(x)]||x,l=s,o='')&&o

console.log=(...x)=>O.textContent+=x.join` `+'\n'

;[["1<SHFT>2<TAB><CAPS>R.KAP.<SPC><SHFT>123", "1@    R.KAP. !23"]
,["<SHFT>ABCDEFG<SHFT>HIJK<SHFT>1<SHFT>2<SHFT>3<SHFT>4567890", "AbcdefgHijk!@#$567890"]
,["<CAPS>THIS<SPC>IS<SPC>IN<SPC>ALL<SPC>CAPS<CAPS><SPC>NOW<SPC>THIS<SPC>IS<SPC>IN<SPC>ALL<SPC>LOWERCASE", "THIS IS IN ALL CAPS now this is in all lowercase"]
,["<TAB><SPC><TAB><SHFT>1", "         !"]
,["<CAPS>WWW<CAPS>.CODEGOLF.STACKEXCHANGE<SHFT>.COM", "WWW.codegolf.stackexchange>com"]
,["PROGRAMMING<CAPS><SPC>IS<SPC><CAPS>AWESOME", "programming IS awesome"]
,["<DEL><RET><DEL><RET><DEL>", ""]
,["<SHFT>HI<SPC>HOW<SPC>ARE<SPC>YOU<SHFT>/<RET><SHFT>I<SPC><SHFT>AM<SPC>O<DEL><SHFT>GOOD<SHFT>1", "Hi how are you?\nI Am Good!"]
,["<SHFT>,<CAPS>RET<CAPS><SHFT>.", "<RET>"]
,["<CAPS>67890,.;'[]<CAPS>", "67890,.;'[]"]
,["<CAPS><SHFT>A", "A"]
,["U<RET><DEL><DEL>I", "i"]
,["RE<DEL><DEL>", ""]
,["", ""]].forEach(t=>{
  var i=t[0],k=t[1],r=F(i)
  console.log(
    k==r?'OK':'KO',i,'\n->',r,k==r?'\n':'(should be ->'+k+')\n'
  )
})
<pre id=O></pre>

edc65
источник
Хорошая работа! :) Если это не так уж и сложно, не могли бы вы проверить, возвращается ли ваша программа и выводит ли она Iдля теста U<RET><DEL><DEL>Iи пустую строку для ввода RE<DEL><DEL>? Я немного разъяснил правила, касающиеся ключа удаления, поэтому, если эти 2 контрольных примера не работают, не могли бы вы также обновить свой код, чтобы он выдавал правильный вывод для этих контрольных примеров? Спасибо!
Р. Кап
Неправильно для этих тестов. Я должен принять другой подход. В то же время, я полагаю , U<RET><DEL>Iдолжен дать iнеI
edc65
Да, вы правы в этом. Обновлено.
Р. Кап