Analizar y procesar la entrada del lenguaje clave

9

¡Analicemos y procesemos Key-Language! Dada la entrada de una secuencia de pulsaciones de teclas del teclado y / o teclas especiales, escriba un programa, función, etc. que genere el producto cuando todas las acciones se procesen según el siguiente teclado:

+-------------------------------------------------------+
| ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | - | + |   |
| ` | 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                         |
+-------------------------------------------------------+                         

Las claves que los personajes reales de salida no que consta de espacios en blanco y son capaces de ser modificados por otras teclas serán conocidos como "teclas de caracteres", y los que modifican la producción de otras llaves o salida de los espacios en blanco serán conocidos como "claves especiales". Las teclas de caracteres del alfabeto, que se mostrarán en la entrada con letras mayúsculas, se pueden modificar con Shifto Caps Lockpara producir letras mayúsculas, y el resto de las teclas de caracteres solo se pueden modificar Shiftpara producir sus caracteres alternativos. Por lo tanto, Aen la entrada corresponde a la a Atecla de caracteres, cuya salida normal es , que corresponde a la tecla de caracteres, tiene una salida normal de y una salida modificada dea y cuya salida modificada, que se puede obtener con la tecla Shifto Caps Lock, es A. Por otra parte,// ?/? obtenible solo con Shifteste tiempo.

Reglas

  • La entrada siempre será una cadena que consta de una secuencia de teclas de caracteres y teclas especiales. La asignación especial de clave a cadena para la entrada (es decir, el formato que se garantiza que estén en la entrada) y sus acciones / salidas correspondientes son las siguientes:

    • <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.
  • Una cadena vacía también es posible como entrada, para la cual la salida no debería ser nada.

  • El uso de cualquier incorporado que resuelva este problema directamente no está permitido.
  • No se permite el uso de lagunas estándar.

Casos de prueba

Presentado en el formato Actual String Input -> Actual String Outputseguido de una explicación para algunos.

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

    La salida se presiona sin presionar 1la 1tecla, luego se mantiene presionada la 2tecla Mayús y se presiona la tecla, lo que da como resultado la @salida. Luego se suelta la tecla Mayús y se presiona Tab, lo que resulta en una sangría de 4 espacios. Seguimiento, las tapas se pulsa la tecla de bloqueo, después de lo cual el R, ., K, A, P, y .se pulsan las teclas, lo que resulta en la salida R.KAP.. Finalmente, un único espacio se salida seguido por cambio resultante en !23ser de salida cuando el 1, 2y 3se pulsan las teclas en el extremo.

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

    La tecla Shift se mantiene presionada seguida de la Atecla, lo que da como resultado la salida Aseguida de la salida bcdefgcuando B-Gse presionan las teclas. Luego, la tecla Shift se mantiene presionada nuevamente por la Htecla, después de lo cual se muestra la salida H, seguido de ijkcuando I-Kse presionan las teclas. Finalmente, todas las 1-4teclas se modifican a medida que se mantiene presionada la tecla shift antes de cada pulsación de tecla, lo que da como resultado la salida !@#$finalizada 567890cuando se 5-0presionan las teclas.

  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)

    La tecla Eliminar se presiona al principio, después de lo cual no sucede nada. Luego, se presiona la tecla Retorno, lo que da como resultado una nueva línea, que se elimina después de presionar nuevamente la tecla de retroceso. Finalmente, se repite la misma secuencia (nueva línea seguida de retroceso). Después de todo esto, la salida es una cadena vacía.

  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>

    La cadena <RET>debe ser la salida real de la cadena. Por lo tanto, esto no debería generar una nueva línea.

  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)

¡Esto es por lo que el código más corto en bytes!

R. Kap
fuente
55
Esa es una extraña tecla de borrar que tienes allí ...
Dennis
1
@ Dennis Bueno, estoy describiendo teclas basadas en el teclado de mi MacBook Pro, donde la tecla Eliminar elimina el carácter anterior. Aunque todavía estoy de acuerdo contigo. Es un diseño bastante extraño.
R. Kap
Ah, eso lo explica. Se llama Retroceso en literalmente cada teclado que he tenido. murmura algo sobre las pulsaciones normales del teclado
Dennis
1
En la prueba # 2, ¿debería ser la salida AbcdefgHijk!@#$567890? Además, en la prueba # 8, se <SHFT>encuentra al final de la cadena, pero las reglas establecen: "Se garantiza que una clave de caracteres tendrá éxito como <SHFT>".
atlasólogo
@atlasólogo Sí, tienes razón, y buena captura! Olvidé actualizarlos.
R. Kap

Respuestas:

6

Código de máquina x86 de 16 bits, 140 139 bytes

Se guardó 1 byte al reemplazar DL con DX en el penúltimo código de operación. También se corrigieron las compensaciones de salto en el desmontaje para que coincida con el volcado hexadecimal.

Dado que la naturaleza de la tarea requiere algunos datos preinicializados, y la respuesta no es un programa completo sino una función, supongo que hay una sección de datos en el programa y el vinculador actualiza rápidamente la dirección de los datos. El marcador de posición de la dirección se indica con '????'.

Esta es una representación hexadecimal del código. Los parámetros son puntero a la cadena de entrada en SI y puntero al búfer de salida en DI. Se supone que las cadenas están terminadas en NULL.

8D1E????89F931D231C0FCAC84C07419D0EA72173C3C74263C41720A3C5A770684F675020C20AAEBE2AAC33C41720B3C5A76F324170402D7EBEC2C27EBF94646AC46240F74154848741748741948741A4848741A39F973B34FEBB04680F601EBAAB020AAAAAAB020EBBCB00AEBB84642EB99

Contenido de la tabla de mapeo (25 bytes):

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

El recuento de bytes representa tanto el código como los datos.

Desmontaje

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

Para el conjunto de instrucciones de 32 bits, el código es absolutamente el mismo, excepto para la primera instrucción que es 2 bytes más larga debido al direccionamiento de 32 bits (8d1d ???????? lea ebx, ds: ??????? ?)

meden
fuente
¡Buen trabajo! :) Si no es demasiado problema, ¿puede verificar si su programa regresa y sale ipara el caso de prueba U<RET><DEL><DEL>Iy una cadena vacía para la entrada RE<DEL><DEL>? Aclaré un poco las reglas con respecto a la clave de eliminación, así que si esos 2 casos de prueba no funcionan, ¿podría actualizar también su código para que produzca la salida correcta para esos casos de prueba? ¡Gracias!
R. Kap
Todos los casos de prueba tuvieron éxito. ¿Por qué <DEL> funcionaría incorrectamente? Es solo una disminución del registro con verificación de límites
meden
Todo bien. Solo quería asegurarme de que su programa funcionara como debería. Gran respuesta.
R. Kap
Necesitamos más casos especiales. Sería más interesante si <DEL> no pudiera eliminar el <RET>. Puedo implementarlo en solo 3 bytes.
meden
1
Al escribir en la línea de comando de un shell que tiene mucho sentido. Pero, fíjate, no estoy pidiendo el cambio de regla. Gracias por el reto.
meden
4

Retina, 136 bytes

Probablemente se pueda jugar más al golf.

<SHFT>
§
<SPC>

<TAB>

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

i (`þ
¶
[^ §]? ÷

Verifique todos los casos de prueba. (Ligeramente modificado para ejecutar todos los casos de prueba a la vez).

Monja permeable
fuente
Mayús + Mayús + A = a en mi teclado.
Neil
@Neil Bueno, para los propósitos de este desafío (y de acuerdo con el teclado de mi Macbook Pro) Caps+Shift+A = A. Hombre, mi teclado es raro ...
R. Kap
MAYÚSCULAS + MAYÚS + A = A. ¿Por qué demonios las mayúsculas invertirán mayúsculas?
gato
1
@cat en millones en el sistema de inversión CAPS shift de Windows, no importa cuántos signos de interrogación escriba. Porque es conveniente y los usuarios están acostumbrados
edc65
1
Aaaand, dos soluciones de 110 bytes: retina.tryitonline.net/… , retina.tryitonline.net/… ... Creo que he terminado por ahora. ;)
Martin Ender
4

JavaScript (ES6), 207

Actualizado para corregir el error con eliminaciones repetidas, incluso algunos bytes más cortos.

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

menos golf

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

Prueba

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
fuente
¡Buen trabajo! :) Si no es demasiado problema, ¿puede verificar si su programa regresa y sale Ipara el caso de prueba U<RET><DEL><DEL>Iy una cadena vacía para la entrada RE<DEL><DEL>? Aclaré un poco las reglas con respecto a la clave de eliminación, así que si esos 2 casos de prueba no funcionan, ¿podría actualizar también su código para que produzca la salida correcta para esos casos de prueba? ¡Gracias!
R. Kap
Incorrecto para estos casos de prueba. Tengo que tomar otro enfoque. Mientras tanto, supongo U<RET><DEL>Ique ino debería darI
edc65
Sí, tienes razón en eso. Actualizado.
R. Kap