Analyser et traiter l'entrée du langage clé

9

Analysons et traitons le langage clé! Étant donné l'entrée d'une séquence de touches clavier et / ou de touches spéciales, écrivez un programme, une fonction, etc. qui génère le produit lorsque toutes les actions sont traitées sur la base du clavier suivant:

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

Les clés qui génèrent des caractères réels non constitués d'espaces et qui peuvent être modifiées par d'autres clés seront appelées "clés de caractères", et celles qui modifient la sortie d'autres clés ou les espaces de sortie seront appelées "clés spéciales". Les touches de caractères alphabétiques, qui seront affichées dans l'entrée avec des lettres majuscules, peuvent être modifiées avec Shiftou Caps Lockpour produire des lettres majuscules, et le reste des touches de caractères ne peut être modifié qu'avec Shiftpour produire leurs caractères alternatifs. Par conséquent, Adans l'entrée correspond à la a Aclé de caractère, dont la sortie normale est aet dont la sortie modifiée, pouvant être obtenue avec la touche Shiftou Caps Lock, est A. D'autre part,/, qui correspond à la / ?touche de caractère, a une sortie normale de /et une sortie modifiée de ?pouvant être obtenue avec uniquement avec Shiftce temps.

Règles

  • L'entrée sera toujours une chaîne composée d'une séquence de touches de caractères et de touches spéciales. La clé spéciale complète pour le mappage de chaîne pour l'entrée (c'est-à-dire le format dans lequel ils sont garantis) et leurs actions / sorties correspondantes sont les suivantes:

    • <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.
  • Une chaîne vide est également possible en entrée, pour laquelle la sortie ne doit être rien.

  • L'utilisation de tout intégré qui résout directement ce problème est interdite.
  • L'utilisation de failles standard est interdite.

Cas de test

Présenté dans le format Actual String Input -> Actual String Outputsuivi d'une explication pour quelques-uns.

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

    Appuyez 1sur la 1touche sans basculer, puis 2appuyez sur la touche Maj et maintenez la touche enfoncée, ce qui donne la @sortie. Ensuite, la touche Maj est relâchée et Tab est enfoncée, ce qui entraîne une indentation espacée de 4. Faisant suite, la touche Verr Maj est pressée, après quoi le R, ., K, A, P, et les .touches sont enfoncées, entraînant la sortie R.KAP.. Enfin, un seul espace est sortie suivi par décalage résultant en !23étant émis lorsque les 1, 2et les 3touches sont enfoncées à la fin.

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

    La touche Maj est maintenue enfoncée suivie de la Atouche, ce qui entraîne la sortie Asuivie de la sortie bcdefglorsque les B-Gtouches sont enfoncées. Ensuite, la touche Shift est maintenue enfoncée , suivie de la Htouche, après quoi la sortie est H, suivie ijklorsque les I-Ktouches sont enfoncées. Enfin, les 1-4touches sont toutes modifiées lorsque la touche Maj est maintenue enfoncée avant chaque pression de touche, ce qui entraîne la fin de la sortie !@#$au 567890moment où les 5-0touches sont enfoncées.

  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 touche de suppression est pressée au début, après quoi rien ne se passe. Ensuite, la touche Retour est enfoncée, ce qui entraîne une nouvelle ligne, qui est supprimée après avoir appuyé à nouveau sur la touche Retour arrière. Enfin, la même séquence (nouvelle ligne suivie d'un retour arrière) est répétée. Après tout cela, la sortie est une chaîne vide.

  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 chaîne <RET>doit être la sortie de chaîne réelle . Ainsi, cela ne devrait pas produire une nouvelle ligne.

  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)

C'est donc le code le plus court en octets gagne!

R. Kap
la source
5
C'est une étrange clé de suppression que vous avez là ...
Dennis
1
@ Dennis Eh bien, je décris des touches basées sur le clavier de mon MacBook Pro, où la touche de suppression supprime le caractère précédent. Je suis toujours d'accord avec toi. C'est une disposition assez bizarre.
R. Kap
Ah, ça explique ça. Cela s'appelle Backspace sur tous les claviers que j'ai jamais possédés. marmonne quelque chose sur les touches du clavier normales
Dennis
1
Dans le test n ° 2, la sortie devrait-elle être AbcdefgHijk!@#$567890? En outre, dans le test # 8, se <SHFT>trouve à la fin de la chaîne, mais les règles stipulent: "Il est garanti qu'une clé de caractère réussira un <SHFT>."
atlasologue
@ atlasologist Oui, vous avez raison et belle prise! J'ai oublié de les mettre à jour.
R. Kap

Réponses:

6

Code machine x86 16 bits, 140 139 octets

1 octet enregistré en remplaçant DL par DX dans l'avant-dernier opcode. Corrections de sauts également corrigées lors du démontage pour correspondre au vidage hexadécimal.

Étant donné que la nature de la tâche nécessite des données pré-initialisées et que la réponse n'est pas un programme complet mais une fonction, je suppose qu'il existe une section de données dans le programme et l'éditeur de liens met rapidement à jour l'adresse des données. L'espace réservé d'adresse est désigné par «????».

Il s'agit d'une représentation hexadécimale du code. Les paramètres sont le pointeur sur la chaîne d'entrée dans SI et le pointeur sur le tampon de sortie dans DI. Les chaînes sont supposées se terminer par NULL.

8D1E????89F931D231C0FCAC84C07419D0EA72173C3C74263C41720A3C5A770684F675020C20AAEBE2AAC33C41720B3C5A76F324170402D7EBEC2C27EBF94646AC46240F74154848741748741948741A4848741A39F973B34FEBB04680F601EBAAB020AAAAAAB020EBBCB00AEBB84642EB99

Contenu de la table de mappage (25 octets):

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

Le nombre d'octets représente à la fois le code et les données.

Démontage:

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

Pour le jeu d'instructions 32 bits, le code est absolument le même, sauf pour la première instruction qui est plus longue de 2 octets en raison de l'adressage 32 bits (8d1d ???????? lea ebx, ds: ??????? ?)

meden
la source
Bon travail! :) Si ce n'est pas trop de problème, pouvez-vous s'il vous plaît vérifier si votre programme retourne et sort ipour le cas de test U<RET><DEL><DEL>Iet une chaîne vide pour l'entrée RE<DEL><DEL>? J'ai clarifié un peu les règles concernant la clé de suppression, donc si ces 2 cas de test ne fonctionnent pas, pourriez-vous également mettre à jour votre code afin qu'il produise la sortie correcte pour ces cas de test? Je vous remercie!
R. Kap
Tous les cas de test ont réussi. Pourquoi <DEL> ne fonctionnerait pas correctement? C'est juste un décrément de registre avec vérification des limites
meden
D'accord. Je voulais juste m'assurer que votre programme fonctionnait comme il se doit. Très bonne réponse.
R. Kap
Nous avons besoin de cas plus spéciaux. Ce serait plus intéressant si <DEL> ne pouvait pas supprimer le <RET>. Je peux l'implémenter en seulement 3 octets.
meden
1
Lorsque vous tapez la ligne de commande d'un shell, cela a parfaitement du sens. Mais attention, je ne demande pas le changement de règle. Merci pour le défi.
meden
4

Rétine, 136 octets

Peut probablement être joué au golf plus loin.

<SHFT>
§
<SPC>

<TAB>

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

i (`þ
¶
[^ §]? ÷

Vérifiez tous les cas de test. (Légèrement modifié pour exécuter tous les tests en même temps.)

Leaky Nun
la source
Maj + Maj + A = a sur mon clavier.
Neil
@Neil Eh bien, aux fins de ce défi (et selon le clavier de mon Macbook Pro) Caps+Shift+A = A. Mec mon clavier est bizarre ...
R. Kap
CAPS + SHIFT + A = A. Pourquoi diable les caps inverseraient-ils le décalage ??
cat
1
@cat en millions sur le changement inversé CAPS du système Windows, quel que soit le nombre de points d'interrogation que vous écrivez. Parce que c'est pratique et que les utilisateurs y sont habitués
edc65
1
Aaaand, deux solutions de 110 octets: retina.tryitonline.net/… , retina.tryitonline.net/… ... Je pense que j'ai fini pour l'instant. ;)
Martin Ender
4

JavaScript (ES6), 207

Mis à jour pour corriger le bogue avec des suppressions répétées, même quelques octets plus courts.

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

moins 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

Tester

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
la source
Bon travail! :) Si ce n'est pas trop de problème, pouvez-vous s'il vous plaît vérifier si votre programme retourne et sort Ipour le cas de test U<RET><DEL><DEL>Iet une chaîne vide pour l'entrée RE<DEL><DEL>? J'ai clarifié un peu les règles concernant la clé de suppression, donc si ces 2 cas de test ne fonctionnent pas, pourriez-vous également mettre à jour votre code afin qu'il produise la sortie correcte pour ces cas de test? Je vous remercie!
R. Kap
Mauvais pour ces cas de test. Je dois adopter une autre approche. Pendant ce temps, je présume que je U<RET><DEL>Ine devrais ipas donnerI
edc65
Oui, vous avez raison à ce sujet. Mise à jour.
R. Kap