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


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

    Перемикач утримується в натиснутому положенні з наступним Aключем, в результаті чого на виході з Aподальшим виходом bcdefgпри B-Gнатисканні клавіш. Потім клавіша перемикання утримується в натиснутому положенні знову змінила Hключ, після чого виходу є H, а потім , ijkколи I-Kклавіші натискати. Нарешті, всі 1-4клавіші модифікуються, коли утримується зсув перед кожним натисканням клавіші, що призводить до завершення виводу !@#$, 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)

    Клавіша видалення натискається на початку, після чого нічого не відбувається. Потім натискається клавіша повернення, що призводить до появи нового рядка, який видаляється після натискання клавіші зворотної області. Нарешті, повторюється та сама послідовність (новий рядок, за яким слідує зворотний простір). Зрештою, вихід - порожній рядок.

  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, де клавіша delete видаляє попередній символ. Я все ще погоджуюся з тобою. Це досить дивна компоновка.
Р. Кап

Ах, це пояснює це. Це називається Backspace буквально на кожній клавіатурі, якою я колись володів. бурмотить щось про звичайне натискання клавіш
Денніс

1
У тесті №2, чи повинен бути результат AbcdefgHijk!@#$567890? Крім того, у тесті № 8 <SHFT>знаходиться в кінці рядка, але правила зазначають: "Гарантовано, що символьна клавіша матиме успіх <SHFT>."
атласолог

@atlasologist Так, ви праві, і приємний лов! Я забув оновити ці.
Р. Кап

Відповіді:


6

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

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

Оскільки характер завдання вимагає певних попередньо ініціалізованих даних, а відповідь - це не повна програма, а функція, я припускаю, що в програмі є розділ даних, і лінкер негайно оновлює адресу даних. Адресу-заповнювача адреси позначають «????».

Це шістнадцяткове подання коду. Параметри - вказівник на рядок введення в SI та вказівник на вихідний буфер у DI. Струни вважаються закінченими NULL.

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>
¶
<РЕТ>
þ
<DEL>
÷
T`L`l` (? <= ^ (. * ¶. * ¶) *). +
T` - =; '[] / \\,. W` \ _ +: "{}? | <> _)! @ # $% ^ & * (LL`§.
§ | ¶

i (`þ
¶
[^ §]? ÷

Перевірте всі тести. (Трохи модифікований для запуску всіх тестів одразу.)


Caps + Shift + A = a на моїй клавіатурі.
Ніл

@Neil Ну, для цілей цього виклику (і відповідно до клавіатури мого Macbook Pro) Caps+Shift+A = A. Людина, моя клавіатура дивна ...
Р. Кап

CAPS + SHIFT + A = A. Чому на Землі будуть обмежувати інвертувати зсув ??
кіт

1
@cat у мільйонах у системі Windows CAPS зворотна зміна, незалежно від того, скільки знаків запитань ви пишете. Тому що це зручно і користувачі звикли до цього
edc65

1
Aaaand, два 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>


Хороша робота! :) Якщо це не так вже й багато проблем, чи можете ви, будь ласка, перевірити, чи повертається та виводиться програма Iдля тестового випадку U<RET><DEL><DEL>Iта порожній рядок для введення RE<DEL><DEL>? Я трохи уточнив правила щодо ключа видалення, тож якщо ці 2 тестові справи не спрацюють, чи можете ви також оновити свій код, щоб він дав правильний вихід для цих тестових випадків? Дякую!
Р. Кап

Неправильно для цих тестових випадків. Я маю взяти інший підхід. У той же час, я вважаю , U<RET><DEL>Iповинен дати iНЕI
edc65

Так, ви з цим правильні. Оновлено.
Р. Кап
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.