キー言語入力を解析して処理する


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

    トグルなしでキーが押さ1れたときに出力し、1Shift 2キーを押しながらキーを押すと@出力されます。次に、Shiftキーを放してTabキーを押すと、4字の字下げが行われます。フォローアップ、Lockキーが押されるキャップは、その後R.KAP、および.キーは出力が得られ、押されていますR.KAP.。最後に、単一のスペースを出力し、その結果シフトが続いている!23場合に出力され12および3キーが端部に押圧されます。

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

    Shiftキーを押した後にキーを押すと、キーが押されたときにA出力がA続き、その後に出力が続きます。次に、Shift キーを押したままキーを押し続けます。その後、出力がになり、続いてキーが押されます。最後に、各キーを押す前にシフトが押されると、キーがすべて変更され、キーが再度押されたときに出力が終了します。bcdefgB-GHHijkI-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キーを押すと新しい行が生成され、Backspaceキーをもう一度押すと削除されます。最後に、同じシーケンス(改行の後にバックスペースが続く)が繰り返されます。このすべての後、出力は空の文字列になります。

  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

ああ、それはそれを説明しています。文字通り、私がこれまで所有していたすべてのキーボードではBackspaceと呼ばれています。通常のキーボードのキープレスについて何かをつぶやく
Dennis

1
テスト#2では、出力があるべきAbcdefgHijk!@#$567890?また、テスト#8では<SHFT>、文字列の最後にありますが、ルールは「文字キーが<SHFT>に続くことが保証されている」と述べています。
アトラスロジスト2016

@atlasologistはい、そうです。更新するのを忘れました。
R. Kap

回答:


6

16ビットx86マシンコード、140 139バイト

最後から2番目のオペコードで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>か?削除キーに関するルールを少し明確にしたので、これらの2つのテストケースが機能しない場合は、コードを更新して、それらのテストケースに対して正しい出力が生成されるようにしてください。ありがとうございました!
R. Kap

すべてのテストケースは成功しました。<DEL>が正しく機能しないのはなぜですか?これは境界チェック付きのレジスターデクリメントです
meden

大丈夫。私はあなたのプログラムが期待通りに機能することを確認したかっただけです。すばらしい答えです。
R. Kap

もっと特別なケースが必要です。<DEL>が<RET>を削除できなかった場合は、さらに興味深いでしょう。わずか3バイトで実装できます。
meden 16

1
完全に意味のあるシェルのコマンドラインを入力するとき。しかし、心に留めておいてください。私はルールの変更を求めているのではありません。挑戦をありがとう。
meden

4

Retina、136バイト

おそらくさらにゴルフをすることができます。

<SHFT>
§
<SPC>

<TAB>

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

i( `þ
¶
[^§]?÷

すべてのテストケースを確認します。(すべてのテストケースを一度に実行するように少し変更されています。)


キーボードのCaps + Shift + A = a。
Neil、

@ニールまあ、この課題の目的のため(そして私のMacbook Proのキーボードによると)Caps+Shift+A = A。キーボードがおかしい...
R. Kap

CAPS + SHIFT + A = A.なぜ地球上でキャップがシフトを反転するのですか?
猫、

1
Windowsシステム上の数百万の@cat CAPSは、いくつの疑問符を書いても、シフトを反転します。便利でユーザーも慣れているため
edc65

1
Aaaandは、2つの110バイトのソリューション:retina.tryitonline.net/...retina.tryitonline.net/...は ...私は今のところ行われていると思います。;)
マーティンエンダー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>か?削除キーに関するルールを少し明確にしたので、これらの2つのテストケースが機能しない場合は、コードを更新して、それらのテストケースに対して正しい出力が生成されるようにしてください。ありがとうございました!
R. Kap

これらのテストケースは間違っています。私は別のアプローチを取る必要があります。その間、私U<RET><DEL>Iは与えiないと思いますI
edc65

はい、あなたはそれについて正しいです。更新しました。
R. Kap
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.