Analizuj i przetwarzaj dane wejściowe w języku klucza

9

Parsujmy i przetwarzajmy Key-Language! Biorąc pod uwagę sekwencję naciśnięć klawiszy i / lub klawiszy specjalnych, napisz program, funkcję itp., Która wyświetli produkt, gdy wszystkie działania zostaną przetworzone w oparciu o następującą klawiaturę:

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

Klawisze że wyjściowe rzeczywiste znaki nie składające się z białych znaków i w stanie być modyfikowane przez inne klawisze będą znane jako „klucze charakter”, a te, które modyfikują wyjście z innymi klawiszami lub wyjście spacje będą znane jako „specjalne klucze”. Klawisze znaków alfabetu, które będą wyświetlane na wejściu wielkimi literami, można modyfikować za pomocą jednego Shiftlub w Caps Lockcelu tworzenia wielkich liter, a pozostałe klawisze znaków można modyfikować tylko za pomocą Shiftich alternatywnych znaków. Dlatego Aw danych wejściowych odpowiada a Aklawisz znaku, którego normalnym wyjściem jest ai którego zmodyfikowanym wyjściem, które można uzyskać za pomocą klawisza Shiftlub Caps Lock, jest A. Z drugiej strony,/, który odpowiada / ?kluczowi znaków, ma normalne wyjście /i zmodyfikowane wyjście ?możliwe do uzyskania tylko z Shifttym czasem.

Zasady

  • Dane wejściowe zawsze będą ciągiem znaków składającym się z sekwencji klawiszy znaków i klawiszy specjalnych. Pełny specjalny klucz do mapowania ciągów dla danych wejściowych (tzn. Format, w którym mają gwarancję, że znajdują się na wejściu) oraz odpowiadające im działania / wyniki są następujące:

    • <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.
  • Pusty ciąg jest również możliwy jako wejście, dla którego wyjście powinno być niczym.

  • Użycie jakiegokolwiek wbudowanego rozwiązania, które bezpośrednio rozwiązuje ten problem, jest niedozwolone.
  • Stosowanie standardowych luk jest niedozwolone.

Przypadki testowe

Przedstawione w formacie, Actual String Input -> Actual String Outputpo którym następuje kilka wyjaśnień.

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

    Wyjście, 1gdy 1klawisz jest wciśnięty bez przełącznika, następnie Shift jest przytrzymywany, a 2klawisz jest wciśnięty, co daje @wynik. Następnie klawisz Shift zostaje zwolniony i klawisz Tab jest wciśnięty, co powoduje wcięcie w 4 odstępach. Idąc za ciosem, klawisz Caps Lock naciśnięty, po upływie którego R, ., K, A, P, i .są naciskane klawisze, w wyniku czego na wyjściu R.KAP.. Wreszcie, pojedyncza przestrzeń wyjście następuje przesunięcie powoduje !23jest wysyłany, kiedy 1, 2i 3naciśnięcie klawisza na końcu.

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

    Klawisz Shift jest przytrzymywany, a następnie Aklawisz, co powoduje, że dane wyjściowe Asą wyświetlane bcdefgpo B-Gnaciśnięciu klawiszy. Następnie klawisz Shift jest wciśnięty ponownie zastąpiony przez Hklucz, po czym wyjściowy H, a następnie ijk, gdy I-Ksą naciskane klawisze. Na koniec wszystkie 1-4klawisze są modyfikowane , gdy klawisz Shift jest przytrzymywany przed każdym naciśnięciem klawisza, co powoduje, że wyjście !@#$kończy się 567890po 5-0ponownym naciśnięciu klawiszy.

  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)

    Klawisz usuwania jest wciskany na początku, po czym nic się nie dzieje. Następnie naciśnięty jest klawisz Return, co powoduje powstanie nowego wiersza, który jest usuwany po ponownym naciśnięciu klawisza Backspace. Wreszcie ta sama sekwencja (nowa linia, po której następuje backspace) jest powtarzana. Po tym wszystkim wynik jest pusty.

  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>

    Ciąg <RET>powinien być faktycznym wyjściem łańcucha. Dlatego nie powinno to generować nowego wiersza.

  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)

To jest więc wygrywa najkrótszy kod w bajtach!

R. Kap
źródło
5
To dziwny klucz Delete, który tam masz ...
Dennis
1
@Dennis Cóż, opisuję klawisze oparte na klawiaturze mojego MacBooka Pro, gdzie klawisz Delete usuwa poprzedni znak. Nadal się z tobą zgadzam. To dość dziwny układ.
R. Kap.
Ach, to wyjaśnia. Nazywa się Backspace na dosłownie każdej klawiaturze, jaką kiedykolwiek miałem. mamrocze coś o normalnych naciśnięciach klawiszy
Dennis
1
Czy w teście nr 2 wynik powinien wynosić AbcdefgHijk!@#$567890? Ponadto w teście nr 8 <SHFT>znajduje się na końcu ciągu, ale reguły mówią: „Zagwarantowane jest, że klucz znaku zastąpi <SHFT>.”
atlasolog
@atlasologist Tak, masz rację i niezły połów! Zapomniałem ich zaktualizować.
R. Kap.

Odpowiedzi:

6

16-bitowy kod maszynowy x86, 140 139 bajtów

Zaoszczędzono 1 bajt, zastępując DL przez DX w przedostatnim kodzie operacji. Poprawiono także przesunięcia przeskoku podczas demontażu, aby dopasować zrzut heksowy.

Ponieważ charakter zadania wymaga pewnych wstępnie zainicjowanych danych, a odpowiedź nie jest pełnym programem, ale funkcją, zakładam, że w programie znajduje się sekcja danych, a linker niezwłocznie aktualizuje adres danych. Symbol zastępczy adresu jest oznaczony przez „????”.

To jest szesnastkowa reprezentacja kodu. Parametry to wskaźnik do łańcucha wejściowego w SI i wskaźnik do bufora wyjściowego w DI. Przyjmuje się, że ciągi znaków kończą się wartością NULL.

8D1E????89F931D231C0FCAC84C07419D0EA72173C3C74263C41720A3C5A770684F675020C20AAEBE2AAC33C41720B3C5A76F324170402D7EBEC2C27EBF94646AC46240F74154848741748741948741A4848741A39F973B34FEBB04680F601EBAAB020AAAAAAB020EBBCB00AEBB84642EB99

Zawartość tabeli mapowania (25 bajtów):

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

Liczba bajtów uwzględnia zarówno kod, jak i dane.

Demontaż:

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

W przypadku zestawu instrukcji 32-bitowych kod jest absolutnie taki sam, z wyjątkiem pierwszej instrukcji, która jest o 2 bajty dłuższa z powodu 32-bitowego adresowania (8d1d ???????? lea ebx, ds: ???????? ?)

meden
źródło
Dobra robota! :) Jeśli nie jest to zbyt duży problem, czy możesz sprawdzić, czy Twój program zwraca wartość wyjściową idla przypadku testowego U<RET><DEL><DEL>Ii pusty ciąg wejściowy RE<DEL><DEL>? Wyjaśniłem trochę zasady dotyczące klucza usuwania, więc jeśli te 2 przypadki testowe nie działają, czy możesz również zaktualizować kod, aby wygenerował prawidłowe dane wyjściowe dla tych przypadków testowych? Dziękuję Ci!
R. Kap
Wszystkie przypadki testowe powiodły się. Dlaczego <DEL> działa niepoprawnie? To tylko
spadek
W porządku. Chciałem tylko upewnić się, że twój program działa tak, jak powinien. Świetna odpowiedź.
R. Kap
Potrzebujemy więcej specjalnych przypadków. Byłoby bardziej interesujące, gdyby <DEL> nie mógł usunąć <RET>. Mogę to zaimplementować w zaledwie 3 bajtach.
środa
1
Podczas pisania w linii poleceń powłoki ma to sens. Ale uwaga, nie proszę o zmianę reguły. Dzięki za wyzwanie.
meden,
4

Siatkówka, 136 bajtów

Prawdopodobnie można dalej grać w golfa.

<SHFT>
§
<SPC>

<TAB>

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

i (`þ
¶
[^ §]? ÷

Sprawdź wszystkie przypadki testowe. (Nieznacznie zmodyfikowany, aby uruchomić wszystkie przypadki testowe jednocześnie).

Leaky Nun
źródło
Caps + Shift + A = a na mojej klawiaturze.
Neil
@Neil Cóż, na potrzeby tego wyzwania (i zgodnie z klawiaturą mojego Macbooka Pro) Caps+Shift+A = A. Człowieku, moja klawiatura jest dziwna ...
R. Kap.
CAPS + SHIFT + A = A. Dlaczego, u licha, miałby odwracać przesunięcie?
kot
1
@cat w milionach w systemie Windows CAPS odwraca przesunięcie, bez względu na to, ile znaków zapytania piszesz. Ponieważ jest to wygodne i użytkownicy są do tego
przyzwyczajeni
1
Aaa, dwa 110-bajtowe rozwiązania: retina.tryitonline.net / ... , retina.tryitonline.net/ ... ... Myślę, że na razie skończone. ;)
Martin Ender
4

JavaScript (ES6), 207

Zaktualizowano, aby naprawić błąd przy wielokrotnym usuwaniu, nawet niektórych bajtów krótszych.

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

mniej golfa

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

Test

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
źródło
Dobra robota! :) Jeśli nie jest to zbyt duży problem, czy możesz sprawdzić, czy Twój program zwraca wartość wyjściową Idla przypadku testowego U<RET><DEL><DEL>Ii pusty ciąg wejściowy RE<DEL><DEL>? Wyjaśniłem trochę zasady dotyczące klucza usuwania, więc jeśli te 2 przypadki testowe nie działają, czy możesz również zaktualizować kod, aby wygenerował prawidłowe dane wyjściowe dla tych przypadków testowych? Dziękuję Ci!
R. Kap
Niewłaściwy dla tych przypadków testowych. Muszę przyjąć inne podejście. Tymczasem zakładam, U<RET><DEL>Iże inie powinienem dawaćI
edc65
Tak, masz rację co do tego. Zaktualizowano
R. Kap