解析和处理键语言输入


9

让我们解析和处理键语言!给定一系列键盘按键和/或特殊键的输入,编写一个程序,功能等,当根据以下键盘处理了所有操作时,该产品就会输出产品:

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

    11没有切换的情况下按下键时输出,然后按住Shift 2键并按下键以产生@输出。然后释放Shift键并按下Tab键,从而产生4个间隔的缩进。跟进,大写锁定键被按下,在这之后R.KAP,和.键按下,导致输出R.KAP.。最后,单个空间被输出,接着移位导致!23被输出时123在末端键被按下。

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

    按住Shift键的同时,按住键A不放,结果是输出,A然后按下键bcdefg时输出B-G。然后,再次按下Shift键,然后再按下该键,其后H输出为H,然后按下ijkI-K键时。最后,将1-4全部修改换档键被每次按键导致输出之前压住!@#$由结束了5678905-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)

    开始时按Delete键,此后什么也没有发生。然后,按回车键将产生新行,在再次按退格键后将其删除。最后,重复相同的序列(换行后跟退格键)。毕竟,输出是一个空字符串。

  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
那是您那里很奇怪的Delete键...
Dennis

1
@Dennis好吧,我在描述基于MacBook Pro键盘的键,其中的Delete键会删除前一个字符。我仍然同意你的看法。这是一个非常奇怪的布局。
R. Kap

嗯,这可以解释。实际上,我曾经拥有的每个键盘上都将其称为Backspace。普通的键盘按键含糊其辞
丹尼斯

1
在测试2中,输出应为AbcdefgHijk!@#$567890?同样,在测试8中,<SHFT>它位于字符串的末尾,但是规则指出:“保证字符键将在<SHFT>之后。”
Atlasologist '16

@atlasologist是的,您是对的,不错!我忘了更新那些。
R. Kap

Answers:


6

16位x86机器代码140个 139字节

通过倒数第二个操作码中的DX替换DL,节省了1个字节。还纠正了反汇编中的跳跃偏移量以匹配十六进制转储。

由于任务的性质需要一些预先初始化的数据,并且答案不是一个完整的程序而是一个函数,因此我认为程序中有一个数据部分,链接程序会立即更新数据地址。地址占位符用“ ????”表示。

这是代码的十六进制表示。参数是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位指令集,代码完全相同,除了第一条指令由于32位寻址而增加了2个字节(8d1d ????????? lea ebx,ds:??????? ?)


干得好!:)如果不是很麻烦,能否请您检查程序是否返回并返回i测试用例的输出U<RET><DEL><DEL>I以及输入RE<DEL><DEL>是否为空字符串?我对删除键做了一些澄清,因此,如果这两个测试用例不起作用,是否还可以更新代码,以便为这些测试用例生成正确的输出?谢谢!
R. Kap

所有测试用例均成功。为什么<DEL>无法正常工作?这只是带有边界检查的寄存器减量
meden

好吧。我只是想确保您的程序能够正常工作。好答案。
R. Kap

我们需要更多特殊情况。如果<DEL>无法删除<RET>会更有趣。我可以用3个字节实现它。
默登

1
在shell的命令行中键入命令非常合理。但是,请注意,我不是在要求更改规则。感谢您的挑战。
默登2016年

4

视网膜,136字节

大概可以打高尔夫球了。

<SHFT>
§
<SPC>

<TAB>

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

我(`þ
¶
[^§]?÷

验证所有测试用例。(稍作修改即可一次运行所有测试用例。)


大写+ Shift + A =我的键盘上的a。
尼尔

@Neil好吧,针对此挑战(根据我的Macbook Pro的键盘)Caps+Shift+A = A。伙计,我的键盘很奇怪...
R. Kap

CAPS + SHIFT + A =A。为什么地球上的大写会反转?

1
无论您编写多少个问号,Windows系统上成千上万个@cat的CAPS都会反转。因为它方便且用户习惯了
edc65 '16

1
Aaaand,两个110字节的解决方案:retina.tryitonline.net / ... ,retina.tryitonline.net / ... ...我想我已经完成了。;)
Martin Ender 2016年

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>是否为空字符串?我对删除键做了一些澄清,因此,如果这两个测试用例不起作用,是否还可以更新代码,以便为这些测试用例生成正确的输出?谢谢!
R. Kap

这些测试用例不正确。我必须采取另一种方法。同时,我相信U<RET><DEL>I应该给iI
edc65

是的,您对此是正确的。更新。
R. Kap
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.