키 언어 입력 구문 분석 및 처리


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수정 된 출력은 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

    토글없이 키를 눌렀을 때 출력 11다음 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출력 하였다 bcdefgB-G키를 누르면된다. 그런 다음 Shift 키를 누른 상태 에서 키를 다시 누른 다음 H출력 을 누른 다음 키를 누를 때마다 H계속됩니다 . 마지막으로, 모든 시프트로 수정 키는 출력 결과 각 누르기 전에 누르고 의해 마무리 때 키를 누르면 다시.ijkI-K1-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)

    아무 것도 발생하지 않으면 처음에 삭제 키를 누릅니다. 그런 다음 Return 키를 누르면 새 줄이 생겨 백 스페이스 키를 다시 누르면 삭제됩니다. 마지막으로 동일한 순서 (새 줄 뒤에 백 스페이스)가 반복됩니다. 이 모든 결과는 빈 문자열입니다.

  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의 키보드를 기반으로 키를 설명하고 있습니다. 여기서 삭제 키는 이전 문자를 삭제합니다. 그래도 여전히 동의합니다. 꽤 이상한 레이아웃입니다.
R. Kap

아, 그 설명입니다. 문자 그대로 모든 키보드에서 백 스페이스라고합니다. 일반적인 키보드 키 누름 에 대해 뭔가를 비웃음
Dennis

1
테스트 # 2에서 출력은 AbcdefgHijk!@#$567890? 또한 테스트 # 8 <SHFT>에서 문자열의 끝에 있지만 규칙 상태는 "문자 키가 <SHFT>에 성공한다는 것을 보장합니다."
atlasologist

@atlasologist 네, 그렇습니다. 나는 그것들을 업데이트하는 것을 잊었다.
R. Kap

답변:


6

16 비트 86 기계어 코드 140 139 바이트

마지막 두 번째 opcode에서 DL을 DX로 교체하여 1 바이트를 절약했습니다. 16 진 덤프와 일치하도록 디스 어셈블리의 점프 오프셋을 수정했습니다.

작업의 성격에는 사전 초기화 된 데이터가 필요하며 대답은 전체 프로그램이 아니라 기능이므로 프로그램에 데이터 섹션이 있고 링커가 데이터의 주소를 즉시 업데이트한다고 가정합니다. 주소 자리 표시자는 '????'로 표시됩니다.

이것은 코드의 16 진 표현입니다. 매개 변수는 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>이 왜 제대로 작동하지 않습니까? 경계 검사를 통한 레지스터 감소
일뿐입니다.

괜찮아. 프로그램이 제대로 작동하는지 확인하고 싶었습니다. 좋은 대답입니다.
R. Kap

더 특별한 경우가 필요합니다. <DEL>이 <RET>를 삭제할 수 없다면 더 흥미로울 것입니다. 단 3 바이트로 구현할 수 있습니다.
meden

1
완벽하게 이해되는 쉘의 명령 행에 입력 할 때. 하지만 규칙 변경을 요구하지는 않습니다. 도전 해 주셔서 감사합니다.
meden

4

레티 나, 136 바이트

아마도 더 골프를 칠 수 있습니다.

<SHFT>
§
<SPC>

<TAB>

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

i (`þ
¶
[^ §]? ÷

모든 테스트 케이스를 확인하십시오. (모든 테스트 케이스를 한 번에 실행하도록 약간 수정했습니다.)


키보드의 Caps + Shift + A = a
Neil

@Neil 글쎄,이 도전의 목적을 위해 (내 Macbook Pro의 키보드에 따라) Caps+Shift+A = A. 내 키보드가 이상하다 ...
R. Kap

CAPS + SHIFT + A = A. 왜 지구상에서 캡이 반전 되는가?
cat

1
Windows 시스템에서 수백만 개의 @cat 많은 물음표를 쓰더라도 CAPS 인버트 시프트. 편리하고 사용자에게 익숙하기 때문에
edc65

1
Aaaand, 두 개의 110 바이트 솔루션 : retina.tryitonline.net/… , retina.tryitonline.net/… ... 나는 지금 끝났다고 생각합니다. ;)
Martin Ender

4

자바 스크립트 (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포기 i해서는 안된다I
edc65

그렇습니다. 업데이트되었습니다.
R. Kap
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.