Your job is to simulate a couple of keystrokes that a user types in.
Input
A string array or string with a delimiter of your choice (outside the range 32-126) containing at least one 'keystroke'.
This array will only contain two types of string: passive keystrokes (single chars) and commands (chars within brackets [ ]).
- Passive keystrokes
- ASCII character codes
[32-126]
- ASCII character codes
- Commands:
[B]: backspace (remove last character added if there is one)[C]: copy all of what has already been written[D]: delete all of what has been written[P]: paste what has been copied
Output
The string produced by the keystrokes.
Examples
['H', 'e', 'l', 'l', 'o'] -> 'Hello'
['H', 'e', 'l', 'l', 'o', ' ', '[C]', '[P]'] -> 'Hello Hello '
['[D]', 'D', '[B]'] -> ''
['H', '[C]', 'i', '[P]', '[C]', '[P]'] -> 'HiHHiH'
['e', '[C]', '[B]', 'I', ' ', 'l', 'i', 'k', '[P]', ' ', 'b', '[P]', '[P]', 's', '!'] -> I like bees!
['N', '[P]'] -> 'N'
['#', '5', '0', 'K', '0', '0', '1', '[D]', '#', 'n', 'o', 't'] -> '#not'
['H', 'o', 'w', ' ', '[D]', 'H', 'e', 'y'] -> 'Hey'
['s', 'u', 'd', '[B]', 'p', '[C]', '[D]', 'I', ' ' , 'h', 'a', 'v', 'e', ' ', '[P]', 'p', 'e', 'r', '!'] -> 'I have supper!'
This is code-golf, so shortest code in bytes wins!
21 Answers 21
Vim, (削除) 76, 64, 62 (削除ここまで), 58 keystrokes
Thanks to Loovjo for saving 7 keystrokes
Did someone say simulate keystrokes? Well then, it's a good thing my favorite language to golf in is all about simulating keystrokes!
:no s :%s/\M[
sB]/<C-v><C-h>
sC]/<C-v><esc>0y$A
sD]/<C-v><esc>"_S
sP]/<C-v><C-r>"
s<bs>\n
S<C-r>"
Input comes in this format:
h
e
l
l
o
[C]
[P]
This is a pretty straightforward answer. It just translates each "command" to the vim keystroke equivalent of that command. Let's take it line by line.
:no s :%s/\M[
This saves a ton of bytes. Vim has a builtin "command line" where you can create mappings, change settings, save files, etc. Here we are creating a mapping. :no is short for :nnoremap which means "When we are in normal mode, substitute this left hand side for this right hand side." Since we are calling :%s/ five different times, this saves a lot. The \M is a nice trick. It means that the following search will be "Very No Magic", which means that the regex [B] will match the literal text [B] rather than a range containing just a B in it. Since the majority of the substitute commands have a brackets in them, we fill in the first one.
Then, we call five substitute commands. It's worth noting why I called <C-v> so many times. Characters like <esc>, <C-v>, <C-r>, etc. are unprintable characters, and must be typed into the command line with a <C-v>.
[B]: backspace. This one is pretty easy. Simply substitute each
[B]withCtrl-h, which is equivalent to backspace in vim.[C]: copy all of what has already been written. This is translated to
<esc>0y$A. This means:<esc> " Escape to normal mode 0 " Move to the beginning of this line y$ " Yank to the end of the line A " Re enter insert mode at the end of this line.We could almost simply do
Yin place of0y$which means "yank the whole line", but this also grabs a newline that we don't want.[D]: delete all of what has been written. This is
<esc>"_S. As before,<esc>exits insert mode so we can run commands. There are some things that are more convenient here. So we doS " Delete this whole line and enter insert mode again "_ " Send it to 'the black hole register'. This is just so that we don't overwrite the main register.[P]: paste what has been copied. This one is also very straightforward. It is just
<C-r>"which meansInsert the contents of register '"'."happens to be the main register that 'y' yanks to.
Now that we have translated all of the commands, we must join all the lines together by removing all of the newline characters. Thanks to our mapping, this is just
s<bs>\n
The <bs> is a backspace, (ASCII 0x08) and we need it because of the [ we filled in.
By now, we have translated the input into vim code, and we just need to run it. So we:
S " Delete this whole line and enter insert mode
<C-r>" " Insert the keystrokes of register '"' as if they were typed by the user
-
\$\begingroup\$ Where's the Insert mode effect of
<C-r>documented? \$\endgroup\$Neil– Neil2016年10月09日 23:31:55 +00:00Commented Oct 9, 2016 at 23:31 -
1\$\begingroup\$ @Neil In general, you can find a key for a specific mode at
:h mode_keystroke. In this case, it would be:h i_ctrl-r\$\endgroup\$DJMcMayhem– DJMcMayhem2016年10月09日 23:34:13 +00:00Commented Oct 9, 2016 at 23:34 -
\$\begingroup\$ @Loovjo Oh sorry, I forgot to mention. Input is expected to be on multiple lines so that I don't have to worry about commas, or the
/gflag. I'll add those details in. \$\endgroup\$DJMcMayhem– DJMcMayhem2016年10月10日 05:25:45 +00:00Commented Oct 10, 2016 at 5:25 -
2\$\begingroup\$ Also, what does
0ii<esc>D@"do? \$\endgroup\$xenia– xenia2016年10月10日 05:42:49 +00:00Commented Oct 10, 2016 at 5:42 -
1\$\begingroup\$ Mappings, eh? :) thanks for the detailed explanation, I always learn something new! \$\endgroup\$Christian Rondeau– Christian Rondeau2016年10月13日 03:24:26 +00:00Commented Oct 13, 2016 at 3:24
CJam, 33 bytes
q~{_[`';"];""L~""]:L~"]1円>3b=}%s~
Explanation
q~ Read an evaluate input list.
{ }% Map over each string in it:
_ Duplicate the string, say S.
[`';"];""L~""]:L~"] Replace it the following list:
[repr(S) '; "];" "L~" "]:L~"]
\ Bring S on top of the stack.
1> Chop off the first char.
3b Base-3 conversion.
= Modular index into the list.
s~ Concatenate and run as CJam code.
The "hash function" 1>3b maps
- single-character strings to 0 (= 0 mod 5),
[B]to 291 (= 1 mod 5),[D]to 297 (= 2 mod 5),[P]to 333 (= 3 mod 5),[C]to 294 (= 4 mod 5).
This value (mod 5) is used as an index into a list of CJam code snippets:
- For single-character strings, say
h, the snippet"h"is returned, which pushes a single-character string to the stack. - For
[B], the snippet;is returned, which pops an element. - For
[D], the snippet];is returned, which clears the stack. - For
[P], the snippetL~is returned, which appends variableLonto the stack. - For
[C], the snippet]:L~is returned, which stores the current stack in the variableL.
These snippets are concatenated and executed; the final stack is printed implicitly by CJam. L is initially the empty list, so the copy buffer is initially "empty".
05AB1E, (削除) 34 (削除ここまで) (削除) 33 (削除ここまで) (削除) 31 (削除ここまで) 27 bytes
Uses CP-1252 encoding.
õUvygiyJë"XJ ̈DU\"4äyáÇ5%è.V
Explanation
õU # initialize X as the empty string
v # for each y in input
ygiyJ # if len(y) == 1 join y with stack
ë # else
"XJ ̈DU\" # push this string
4ä # split into 4 parts (of size [2,1,2,1])
yá # push only letters of y
Ç5% # mod its ascii code by 5
è # index into the string above with this
.V # evaluate as 05AB1E code
The pairs of functions evaluated in the code above are:
DU # [C] -> duplicate and store in X
XJ # [P] -> push X and join with stack
̈ # [B] -> remove last char of string
\ # [D] -> remove top of stack
Saved 4 bytes using the mod 5 trick from Lynn's CJam answer
Jelly, (削除) 50 51 (削除ここまで) 48 bytes
Ṿ";;μṭ"Ṗ"ø©"ḣ0";®"
L>1a2ị$i@"BCDP0"ịÇ
Ç€"6Ṗ©";FV
How?
Ṿ";;μṭ"Ṗ"ø©"ḣ0";®" - Link 1, CreateCodeLookupValueList: keystroke
"Ṗ"ø©"ḣ0";®" - list of strings, ["Ṗ","ø©","ḣ0"";®"] - these are Jelly code for:
Ṗ : pop (i.e. delete last entry)
ø© : niladic separation and copy to register (i.e. copy)
ḣ0 : head to 0 (i.e. delete all entries)
;® : concatenate with value of register (i.e. paste)
μ - monadic chain separation
Ṿ - uneval - make a Jelly code version of the keystroke
e.g. "I" -> ""I""
"; - string literal ";" |
; - concatenate e.g. ";I" v
ṭ - tack, to make the list ["Ṗ","ø©",";®",""I""]
a keystroke - a command will evaluate to a string like
""[C]"" but wont be accessed)
L>1a2ị$i@"BCDP0"ịÇ - Link 2, ConvertAKeystokeToJellyCodeString: keystroke
L>1 - length greater than 1? (i.e. isCommand?)
$ - last two links as a monad
a - and
2ị - index 2 of the keystroke (0 due to and for a passive keystroke)
"BCDP0" - Literal string "BCP0"
i@ - find first matching index of, with reversed arguments
ị - index into
Ç - call last link (1) as a monad (get code to replace this keystroke)
Ç€"6Ṗ©";FV - Main link: list of keystrokes
Ç€ - call last link (2) as a monad (convert to Jelly code)
"6Ṗ©" - literal string "6Ṗ©" - setup the register with an empty string:
6 :literal " ";
Ṗ : pop the space to give an empty string;
© : places it into the register
; - concatenate (put that at the front)
F - flatten list (lists and strings are equivalent in Jelly)
V - evaluate the string
For example
The input:
['e', '[C]', '[B]', 'I', ' ', 'l', 'i', 'k', '[P]', ' ', 'B', '[P]', '[P]', 's', '!']
Becomes the Jelly code:
"6Ṗ©;"e"ø©Ṗ;"I";" ";"l";"i";"k";®;" ";"B";®;®;"s";"!""
Which then evaluates to
"I like Bees!"
- with a capital 'B' as a test case, since before I fixed a bug it would have returned "I likeees!"
-
1\$\begingroup\$ I'm not sure it's a valid test case, but I tried with an overly complex string and this appears to fail:
['e', 'e', 'e', '[B]', '[C]', '[B]', '[D]', 'I', ' ', 'l', 'i', 'k', '[P]', '[B]', ' ', 'b', '[P]', 's', '!']. \$\endgroup\$Dom Hastings– Dom Hastings2016年10月10日 07:45:51 +00:00Commented Oct 10, 2016 at 7:45 -
\$\begingroup\$ Ah - yes I missed this edge case, there is a copy before deleting the entire string and the code I wrote ignores it. I will look at it a little later, thanks for notifying me. \$\endgroup\$Jonathan Allan– Jonathan Allan2016年10月10日 07:48:25 +00:00Commented Oct 10, 2016 at 7:48
-
\$\begingroup\$ OK I fixed that up and it actually saves bytes too! \$\endgroup\$Jonathan Allan– Jonathan Allan2016年10月10日 08:21:22 +00:00Commented Oct 10, 2016 at 8:21
JavaScript (ES6), (削除) 84 (削除ここまで) (削除) 80 (削除ここまで) (削除) 77 (削除ここまで) 76 bytes
Saved 3 bytes thanks to @Neil, 1 more thanks to @edc65
x=>x.reduce((s,[c,z])=>z<'C'?s.slice(0,-1):z<'D'?t=s:z<'P'?"":s+=z?t:c,t="")
.map is two bytes longer:
x=>x.map(([c,z])=>s=z<'C'?s.slice(0,-1):z<'D'?t=s:z<'P'?"":s+=z?t:c,s=t="")&&s
Test snippet
f=x=>x.reduce((s,[c,z])=>z<'C'?s.slice(0,-1):z<'D'?t=s:z<'P'?"":s+=z?t:c,t="")
console.log(f(['e', '[C]', '[B]', 'I', ' ', 'l', 'i', 'k', '[P]', ' ', 'b', '[P]', '[P]', 's', '!']))
<button onclick="console.log(f(I.value.split('\n')))">Run</button>
<br><textarea id=I rows=10>H
e
l
l
o
[C]
[P]</textarea><br>
-
\$\begingroup\$ The difference is that you can save 3 bytes on the
reduceversion by using(s,[c,z]). \$\endgroup\$Neil– Neil2016年10月09日 23:37:00 +00:00Commented Oct 9, 2016 at 23:37 -
\$\begingroup\$ @Neil Nice! That saves a byte on the
.mapversion too. \$\endgroup\$ETHproductions– ETHproductions2016年10月10日 00:21:04 +00:00Commented Oct 10, 2016 at 0:21 -
\$\begingroup\$
x=>x.reduce((s,[c,z])=>z<'C'?s.slice(0,-1):z<'D'?t=s:z<'P'?'':s+=z?t:c,t='')1 byte less. Curiously undefined < any char is false \$\endgroup\$edc65– edc652016年10月10日 09:55:40 +00:00Commented Oct 10, 2016 at 9:55 -
\$\begingroup\$
x=>x.reduce((s,[c,z])=>z<'C'?s.slice(0,-1):z<'D'?t=s:z<'P'?"":z?t:s+c,t="")saves one more character. If z is truthy, paste, else add char to output. \$\endgroup\$Grax32– Grax322016年10月10日 18:51:49 +00:00Commented Oct 10, 2016 at 18:51 -
\$\begingroup\$ @Grax when pasting you have to add to the current output, so
z?s+t:s+cthat is 1 byte more thans+=z?t:c\$\endgroup\$edc65– edc652016年10月10日 20:33:57 +00:00Commented Oct 10, 2016 at 20:33
Python 2, (削除) 96 (削除ここまで) (削除) 95 (削除ここまで) 93 bytes
r=c=""
for o in input():c=[c,r][x=="[C]"];r=[r+c,r[:-1],r,"",r+o][ord(o[1:2]or"E")%5]
print r
-
\$\begingroup\$ Can you move the
or"E"to the definition ofxto save a space? \$\endgroup\$xnor– xnor2016年10月10日 00:27:52 +00:00Commented Oct 10, 2016 at 0:27 -
\$\begingroup\$ @xnor I believe so. \$\endgroup\$orlp– orlp2016年10月10日 00:28:32 +00:00Commented Oct 10, 2016 at 0:28
-
1\$\begingroup\$ Actually, it looks like defining
xisn't worth it. Thex=="C"can just beo=="[C]". \$\endgroup\$xnor– xnor2016年10月10日 01:10:36 +00:00Commented Oct 10, 2016 at 1:10
Perl, (削除) 53 (削除ここまで) 50 bytes
Includes +1 for -p
Give input on STDIN terminated by newlines (the last newline may be left out, so it counts as a string separated by newlines):
keystrokes.pl
H
e
[C]
[D]
a
b
[B]
[P]
z
^D
gives
aHez
keystrokes.pl:
#!/usr/bin/perl -p
$\.=/^.$/?$&:/P/?$a:(/C/?$a=$\:chop($\x=/B/))x0}{
Almost caught the Jelly answer but the fiend escaped to 48 bytes...
Python (削除) 120 119 (削除ここまで) 116 bytes
f=lambda s,r='',c='':f(s[1:],*{'B':(r[:-1],c),'C':(r,r),'D':('',c),'P':(r+c,c),'':(r+s[0],c)}[s[0][1:2]])if s else r
A recursive function with input, s, a list of the key-strokes.
Each recursive call updates the return text, r and, in the case of a [C], the clipboard, c until s is empty.
The new values of r and c are found by indexing into a dictionary, {...}, and passed with unpacking, *. For the passive keystrokes s[0][1:2]will return an empty string and the key '' will be used instead.
-
\$\begingroup\$ Might I ask why you define the lambda as
lambda s,r='',c=''instead oflambda s,r,c=''? \$\endgroup\$L. Steer– L. Steer2016年10月14日 15:23:08 +00:00Commented Oct 14, 2016 at 15:23 -
\$\begingroup\$ The specification is that we take an input array of characters (here
s) so the function needs to work with no other input. \$\endgroup\$Jonathan Allan– Jonathan Allan2016年10月14日 15:36:39 +00:00Commented Oct 14, 2016 at 15:36 -
\$\begingroup\$ My apologies, reading comprehension failure. \$\endgroup\$L. Steer– L. Steer2016年10月14日 17:09:31 +00:00Commented Oct 14, 2016 at 17:09
Haskell, (削除) 136 133 130 (削除ここまで) 127 bytes
k c b(('[':m:_):i)|m<'C'=k c[q|b>"",q<-init b]i|m<'D'=k b b i|m<'P'=k c""i|1<3=k c(b++c)i
k c b(s:i)=k c(b++s)i
k c b[]=b
k""""
Explanation: k performs a tail recursion over a list of commands. b is the buffer in which the string is constructed, c saves the copied part.
k c b ("[B]":i) = k c (take(length b - 1)b) i -- remove last element of buffer
k c b ("[C]":i) = k b b i -- set copy to buffer
k c b ("[D]":i) = k c "" i -- clear the buffer
k c b ("[P]":i) = k c (b++c) i -- append content of copy to the buffer
k c b (s:i) = k c (b++s) i -- append char to the buffer
k c b [] = b -- command list is empty, return buffer
f = k "" "" -- initialise copy and buffer with empty strings
Edit: To save some bytes the commands[B][C][D][P]are no longer matched exactly but compared: less than 'C'? -> B and so on.
Thanks to @nimi for saving 3 bytes.
-
\$\begingroup\$ @nimi
init bthrows an exception ifbis the empty list. \$\endgroup\$Laikoni– Laikoni2016年10月10日 16:11:49 +00:00Commented Oct 10, 2016 at 16:11 -
\$\begingroup\$ @nimi That's clever, thanks! As for the anonymous function I somehow had in mind that anonymous functions are only acceptable when they are the only statement and there are no other helper functions. However searching Meta turned up nothing like that, so I guess it's ok. \$\endgroup\$Laikoni– Laikoni2016年10月10日 18:02:53 +00:00Commented Oct 10, 2016 at 18:02
-
2\$\begingroup\$ Here it is. It's allowed to declare helper functions for expressions that evaluate to functions. \$\endgroup\$nimi– nimi2016年10月10日 18:15:52 +00:00Commented Oct 10, 2016 at 18:15
Mathematica, 100 bytes
""<>Fold[Switch[#2,"[B]",Most@#~Check~{},"[C]",a=#,"[D]",{},"[P]",#~Join~a,_,Append@##]&,a={};{},#]&
Anonymous function. Takes a list of strings as input and returns a string as output. Ignore any messages generated.
Java 7, (削除) 207 (削除ここまで) 203 bytes
String c(String[]a){String r="",c=r;for(String s:a){int k=s.length(),l=r.length(),z;if(k>1){z=s.charAt(1);r=z<67?l>0?r.substring(0,l-1):"":z<68?r:z<69?"":z<81?r+c:r+s;c=z==67?r:c;}r+=k<2?s:"";}return r;}
This can most definitely be golfed some more, (削除) but this is my initial answer. Will edit after I found something to remove those replaced with equals-checks.. (削除ここまで)charAt, but can probably still be golfed..
Ungolfed & test code:
class M{
static String c(final String[] a) {
String r = "",
c = r;
for(String s : a){
int k = s.length(),
l = r.length(),
z;
if(k > 1){
z = s.charAt(1);
r = z < 67
? l > 0
? r.substring(0, l-1)
: ""
: z < 68
? r
: z < 69
? ""
: z < 81
? r + c
: r + s;
c = z == 67
? r
: c;
}
r += k < 2
? s
: "";
}
return r;
}
public static void main(String[] a){
System.out.println(c(new String[]{ "H", "e", "l", "l", "o" }));
System.out.println(c(new String[]{ "H", "e", "l", "l", "o", " ", "[C]", "[P]" }));
System.out.println(c(new String[]{ "[D]", "D", "[B]" }));
System.out.println(c(new String[]{ "H", "[C]", "i", "[P]", "[C]", "[P]" }));
System.out.println(c(new String[]{ "e", "[C]", "[B]", "I", " ", "l", "i", "k", "[P]", " ", "b", "[P]", "[P]", "s", "!" }));
System.out.println(c(new String[]{ "N", "[P]" }));
System.out.println(c(new String[]{ "#", "5", "0", "K", "0", "0", "1", "[D]", "#", "n", "o", "t" }));
System.out.println(c(new String[]{ "H", "o", "w", " ", "[D]", "H", "e", "y" }));
System.out.println(c(new String[]{ "s", "u", "d", "[B]", "p", "[C]", "[D]", "I", " ", "h", "a", "v", "e", " ", "[P]", "p", "e", "r", "!" }));
}
}
Output:
Hello
Hello Hello
HiHHiH
I like bees!
N
#not
Hey
I have supper!
PHP, 131 Bytes
17 Bytes save by @IsmaelMiguel ternary operator
<?$c=[];foreach($_GET[a]as$v)($t=$v[1])!=P?$t!=C?$t!=B?$t!=D?$o[]=$v:$o=[]:array_pop($o):$c=$o:$o=array_merge($o,$c);echo join($o);
-
1\$\begingroup\$ 147 bytes:
<?$c=[];foreach($_GET[a]as$k=>$v)$v=="[P]"?$o=array_merge($o,$c):($v=="[C]"?$c=$o:($v=="[B]"?array_pop($o):$v=="[D]"?$o=[]:$o[]=$v));echo join($o);. (replaced your wholeif()chain with a chain of trenary operations). \$\endgroup\$Ismael Miguel– Ismael Miguel2016年10月09日 23:46:41 +00:00Commented Oct 9, 2016 at 23:46 -
\$\begingroup\$ @IsmaelMiguel Thank You. I had no desire to use the operator \$\endgroup\$Jörg Hülsermann– Jörg Hülsermann2016年10月09日 23:58:46 +00:00Commented Oct 9, 2016 at 23:58
-
\$\begingroup\$ I can see why. It looks so ugly and ... it really is something that hurts the eye. \$\endgroup\$Ismael Miguel– Ismael Miguel2016年10月10日 00:02:02 +00:00Commented Oct 10, 2016 at 0:02
PHP, 108 bytes
for(;null!==$s=$argv[++$i];)($g=$s[1])!=B?$g!=C?$g!=D?$o.=$g!=P?$s:$c:$o='':$c=$o:$o=substr($o,0,-1);echo$o;
Uses a string based approach rather than an array based one.
Use like:
php -r "for(;null!==$s=$argv[++$i];)($g=$s[1])!=B?$g!=C?$g!=D?$o.=$g!=P?$s:$c:$o='':$c=$o:$o=substr($o,0,-1);echo$o;" a b "[C]" "[B]" "[P]" "[C]" "[D]" j "[P]"
edit: saved 8 bytes by fiddling the order of the ?:s and making them negative to avoid having to use so many brackets;
-
\$\begingroup\$
$s=$argv[++$i]instead ofnull!==$s=$argv[++$i]if you use PHP >7 you could write$s=$argv[++$i]??0to skip the notice \$\endgroup\$Jörg Hülsermann– Jörg Hülsermann2016年10月10日 15:12:27 +00:00Commented Oct 10, 2016 at 15:12 -
1\$\begingroup\$ It's not there to skip the notice but to allow you to enter
'0'seeing as how'0'is false. There are so many other notices that skipping that one in particular seems like a waste of time. \$\endgroup\$user59178– user591782016年10月10日 15:27:17 +00:00Commented Oct 10, 2016 at 15:27
SpecBAS - 216 bytes
1 s,ドルt$="": INPUT a$: DIM b$(SPLIT a,ドルNOT ",")
2 FOR EACH l$ IN b$()
3 CASE l$
4 WHEN "[B]": s$=s$( TO LEN s$-1)
5 WHEN "[C]": t$=s$
6 WHEN "[D]": s$=""
7 WHEN "[P]": s$=s$+t$
8 OTHERWISE : s$=s$+l$
9 END CASE
10 NEXT l$: ?s$
Input is given as a string with commas, which is then turned into array.
V, 49 bytes
íÛBÝ/
íÛCÝ/0y$A
íÛDÝ/"_S
íÛPÝ/"
íî
0éiD@"
Since this contains unprintable characters, here is a hexdump:
0000000: eddb 42dd 2f16 080a eddb 43dd 2f16 1b30 ..B./.....C./..0
0000010: 7924 410a eddb 44dd 2f16 1b22 5f53 0aed y$A...D./.."_S..
0000020: db50 dd2f 1612 220a edee 0a30 e969 4440 .P./.."....0.iD@
0000030: 22
This is just a direct translation of my vim answer so that I could compete with Jelly. Unfortunately, I'm still one byte over, but I'm still working on the last one. :)
I'm more proud of that answer anyway, so if you want a very detailed explanation, read that one instead.
Actually, 56 bytes
''j"'[B]"'XaÆ"'[C]""k;╗i"aÆ"'[P]""╜i"aÆ"'[D]"'éaÆ''+ƒkΣR
Explanation:
''j"'[B]"'XaÆ"'[C]""k;╗i"aÆ"'[P]""╜i"aÆ"'[D]"'éaÆ''+ƒkΣR
''j insert an apostrophe between every pair of commands
"'[B]"'XaÆ"'[C]""k;╗i"aÆ"'[P]""╜i"aÆ"'[D]"'éaÆ replace:
"'[B]"'XaÆ "'[B]" with "X"
"'[C]""k;╗i"aÆ "'[C]" with "k;╗i"
"'[P]""╜i"aÆ "'[P]" with "╜i"
"'[D]"'éaÆ "'[D]" with "é"
''+ prepend an apostrophe
now the input has been converted to the equivalent Actually program ("'<character>" pushes the character, "X" removes the last character, "k;╗i" saves the current stack state to a register, and "╜i" pushes the saved stack state)
ƒ execute the code
kΣ concatenate the characters
R reverse the string
Java, 181
String v(String[]a){String r="",c=r;for(String s:a){try{int p=s.charAt(1)%5;r=p<1?r+c:p>2?"":p==1?r.length()<2?"":r.split(".$")[0]:r;c=p==2?r:c;}catch(Exception e){r+=s;}}return r;}
More readable version:
String v(String[]a){
String r="",c=r;
for(String s:a){
try{
int p=s.charAt(1)%5;
r= p<1
? r+c
: p>2
? ""
:p==1
? r.length()<2
?""
:r.split(".$")[0]
:r;
c=p==2?r:c;
}catch(Exception e){
r+=s;
}
}return r;
}
-
\$\begingroup\$ You can save some byte (1 or 2) by changing your try catch into a
if(s.length()>1){...}else\$\endgroup\$AxelH– AxelH2016年10月11日 11:13:08 +00:00Commented Oct 11, 2016 at 11:13 -
\$\begingroup\$ and change the
p==1intop<2\$\endgroup\$AxelH– AxelH2016年10月11日 11:29:47 +00:00Commented Oct 11, 2016 at 11:29
MATL, 46 bytes
vXKx"@gtnq?2)XJ66=?3L)}J67=?XK}J68=?vx}K]]]]&h
Try it online! Or verify all test cases.
Explanation
v % Push empty array
XK % Copy to clipboard K. This initiallizes it as empty
x % Delete
" % Implicitly input cell array. For each
@g % Push current cell's contents
t % Duplicate elements
n % Number of elements
q? % If more then 1
2) % Get second char. Copy to clipboard J
66=? % If it ss 'B'
3L) % Remove last element from string built up to now
} % Else
J67=? % If it was a 'C'
XK % Copy string built up to now into clipboard K
} % Else
J68=? % If was a 'D'
vx % Delete stack. This deletes string built up to now, if any
} % Else: it was a 'P'
K % Paste from clipboard K
] % End if
] % End if
] % End if
] % End if
&h % Horizontally concatenate stack
% Implicitly end for
% Implicitly display
TCL, 186 bytes
proc t w {foreach "B C P N D r Q" [list {[string range $r 0 end-1]} {[set Q $r]} {$r$Q} {$r$g}] break;foreach g $w {eval "set c \$[string index ${g}N 1]";eval "set r \"$c\""};return $r}
Nicely formatted:
proc t w {
foreach "B C P N D r Q" [list {[string range $r 0 end-1]} {[set Q $r]} {$r$Q} {$r$g}] break;
foreach g $w {
eval "set c \$[string index ${g}N 1]"
eval "set r \"$c\""
}
return $r
}
I just wanted to prove I could do this in TCL
-
\$\begingroup\$ You can save bytes: replace
foreachbylmap;returnbyset x. This is what I can say on a quick glance. \$\endgroup\$sergiol– sergiol2017年02月15日 02:08:16 +00:00Commented Feb 15, 2017 at 2:08
Scala, 158 bytes
(i:Seq[String])=>(("","")/:i){case((a,c),k)=>if(k.size<2)(a+k,c)else
if(k=="[B]")(a dropRight 1,c)else
if(k=="[C]")(a,a)else
if(k=="[D]")("",c)else(a+c,c)}._1
Ungolfed:
(i:Seq[String]) => i.foldLeft(("", "")){
case ((res,clipboard),key) =>
if (k.size == 1) (res+key,clipboard)
else if (k=="[B]") (res dropRight 1, clipboard)
else if (k=="[C]") (res, res)
else if (k=="[D]") ("", clipboard)else(acc+clipboard,clipboard)
}._1
Solves this problem as a fold with the result and the clipboard as accumulator. Sadly, scala doesn't have a ternary conditional operator, but instead uses if else as an expression.
PHP 7.1, (削除) 95 (削除ここまで) 92 bytes
Note: requires PHP 7.1 for negative string offsets.
for(;n|$i=$argv[++$x];)($l=$i[1])?$l^r?$l^s?$l^t?$o.=$c:$o="":$c=$o:$o[-1]="":$o.=$i;echo$o;
Without negative string offsets (101 bytes):
php -r 'for(;n|$i=$argv[++$x];)($l=$i[1])?$l^r?$l^s?$l^t?$o.=$c:$o="":$c=$o:$o=substr($o,0,-1):$o.=$i;echo$o;' e [C] [B] I ' ' l i k [P] ' ' b [P] [P] s ! 2>/dev/null;echo
Run like this:
php -nr 'for(;n|$i=$argv[++$x];)($l=$i[1])?$l^r?$l^s?$l^t?$o.=$c:$o="":$c=$o:$o[-1]="":$o.=$i;echo$o;' e [C] [B] I ' ' l i k [P] ' ' b [P] [P] s !;echo
> I like bees!
Explanation
for(
;
n|$i=$argv[++$x]; # Iterates over the input until null.
)
($l=$i[1])? # Check if this item is a command, if so set to $l
$l^r? # If the command is not B
$l^s? # If the command is not C
$l^t? # If the command is not D
$o.=$c # Then it's P, so paste the clipboard ($c)
:$o="" # It's D, so delete output
:$c=$o # It's C, so copy output to clipboard
:$o[-1]="" # It's B, so remove the last output char
:$o.=$i; # No command, add the current item to the output.
echo$o; # Print the output.
Tweaks
- Saved 3 bytes by combining the output handling with the command handling
-
\$\begingroup\$ Nice to see a PHP entry explained in detail :) \$\endgroup\$Emigna– Emigna2016年10月10日 21:34:24 +00:00Commented Oct 10, 2016 at 21:34
[D]where it's not the only one used, so the code won't just besplit('[D]')[1]or something. \$\endgroup\$[D]\$\endgroup\$