33
\$\begingroup\$

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
    1. ASCII character codes [32-126]
  • Commands:
    1. [B] : backspace (remove last character added if there is one)
    2. [C] : copy all of what has already been written
    3. [D] : delete all of what has been written
    4. [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 , so shortest code in bytes wins!

\$\endgroup\$
5
  • \$\begingroup\$ FYI I found a bug in my code, may I suggest a test case with a capital B for bees :) \$\endgroup\$ Oct 10, 2016 at 1:19
  • \$\begingroup\$ There should also be an example with [D] where it's not the only one used, so the code won't just be split('[D]')[1] or something. \$\endgroup\$
    – mbomb007
    Oct 10, 2016 at 13:25
  • \$\begingroup\$ @mbomb007, I added test cases (#8, #9) \$\endgroup\$
    – Daniel
    Oct 10, 2016 at 13:32
  • \$\begingroup\$ And I think mbomb007 was asking for a test case with multiple deletions. \$\endgroup\$ Oct 10, 2016 at 13:35
  • \$\begingroup\$ @MartinEnder, oh I thought he wanted one where there are commands other than [D] \$\endgroup\$
    – Daniel
    Oct 10, 2016 at 13:36

21 Answers 21

34
\$\begingroup\$

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] with Ctrl-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 Y in place of 0y$ 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 do

      S         " 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 means Insert 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
\$\endgroup\$
6
  • \$\begingroup\$ Where's the Insert mode effect of <C-r> documented? \$\endgroup\$
    – Neil
    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
    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 /g flag. I'll add those details in. \$\endgroup\$
    – DJMcMayhem
    Oct 10, 2016 at 5:25
  • 2
    \$\begingroup\$ Also, what does 0ii<esc>D@" do? \$\endgroup\$
    – xenia
    Oct 10, 2016 at 5:42
  • 1
    \$\begingroup\$ Mappings, eh? :) thanks for the detailed explanation, I always learn something new! \$\endgroup\$ Oct 13, 2016 at 3:24
9
\$\begingroup\$

CJam, 33 bytes

q~{_[`';"];""L~""]:L~"]\1>3b=}%s~

Try it online!

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 snippet L~ is returned, which appends variable L onto the stack.
  • For [C], the snippet ]:L~ is returned, which stores the current stack in the variable L.

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”.

\$\endgroup\$
7
\$\begingroup\$

05AB1E, 34 33 31 27 bytes

Uses CP-1252 encoding.

õUvygiyJë"XJ¨DU\"4äyáÇ5%è.V

Try it online!

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

\$\endgroup\$
7
\$\begingroup\$

Jelly, 50 51 48 bytes

Ṿ”;;µṭ“Ṗ“ø©“ḣ0“;®”
L>1a2ị$i@“BCDP0”ịÇ
Ç€“⁶Ṗ©”;FV

TryItOnline
Or all test cases

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)

Ç€“⁶Ṗ©”;FV - Main link: list of keystrokes
Ç€         - call last link (2) as a monad (convert to Jelly code)
  “⁶Ṗ©”    - literal string "⁶Ṗ©" - setup the register with an empty string:
                 ⁶ :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:
    "⁶Ṗ©;“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!"

\$\endgroup\$
3
  • 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\$ 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\$ Oct 10, 2016 at 7:48
  • \$\begingroup\$ OK I fixed that up and it actually saves bytes too! \$\endgroup\$ Oct 10, 2016 at 8:21
7
\$\begingroup\$

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>

\$\endgroup\$
6
  • \$\begingroup\$ The difference is that you can save 3 bytes on the reduce version by using (s,[c,z]). \$\endgroup\$
    – Neil
    Oct 9, 2016 at 23:37
  • \$\begingroup\$ @Neil Nice! That saves a byte on the .map version too. \$\endgroup\$ 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
    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
    Oct 10, 2016 at 18:51
  • \$\begingroup\$ @Grax when pasting you have to add to the current output, so z?s+t:s+c that is 1 byte more than s+=z?t:c \$\endgroup\$
    – edc65
    Oct 10, 2016 at 20:33
7
\$\begingroup\$

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
\$\endgroup\$
3
  • \$\begingroup\$ Can you move the or"E" to the definition of x to save a space? \$\endgroup\$
    – xnor
    Oct 10, 2016 at 0:27
  • \$\begingroup\$ @xnor I believe so. \$\endgroup\$
    – orlp
    Oct 10, 2016 at 0:28
  • 1
    \$\begingroup\$ Actually, it looks like defining x isn't worth it. The x=="C" can just be o=="[C]". \$\endgroup\$
    – xnor
    Oct 10, 2016 at 1:10
5
\$\begingroup\$

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...

\$\endgroup\$
0
4
\$\begingroup\$

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

Ideone

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.

\$\endgroup\$
3
  • \$\begingroup\$ Might I ask why you define the lambda as lambda s,r='',c='' instead of lambda s,r,c=''? \$\endgroup\$
    – L. Steer
    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\$ Oct 14, 2016 at 15:36
  • \$\begingroup\$ My apologies, reading comprehension failure. \$\endgroup\$
    – L. Steer
    Oct 14, 2016 at 17:09
4
\$\begingroup\$

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""""

Try it on Ideone.

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.

\$\endgroup\$
3
  • \$\begingroup\$ @nimi init b throws an exception if b is the empty list. \$\endgroup\$
    – Laikoni
    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
    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
    Oct 10, 2016 at 18:15
3
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

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 equals-checks.. replaced with charAt, but can probably still be golfed..

Ungolfed & test code:

Try it here.

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!
\$\endgroup\$
2
\$\begingroup\$

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);
\$\endgroup\$
3
  • 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 whole if() chain with a chain of trenary operations). \$\endgroup\$ Oct 9, 2016 at 23:46
  • \$\begingroup\$ @IsmaelMiguel Thank You. I had no desire to use the operator \$\endgroup\$ 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\$ Oct 10, 2016 at 0:02
1
\$\begingroup\$

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;

\$\endgroup\$
2
  • \$\begingroup\$ $s=$argv[++$i] instead of null!==$s=$argv[++$i] if you use PHP >7 you could write $s=$argv[++$i]??0 to skip the notice \$\endgroup\$ 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
    Oct 10, 2016 at 15:27
1
\$\begingroup\$

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.

enter image description here

\$\endgroup\$
1
\$\begingroup\$

V, 49 bytes

íÛBÝ/
íÛCÝ/0y$A
íÛDÝ/"_S
íÛPÝ/"
íî
0éiD@"

Try it online!

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.

\$\endgroup\$
1
\$\begingroup\$

Actually, 56 bytes

''j"'[B]"'XaÆ"'[C]""k;╗i"aÆ"'[P]""╜i"aÆ"'[D]"'éaÆ''+ƒkΣR

Try it online!

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
\$\endgroup\$
1
\$\begingroup\$

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;
}
\$\endgroup\$
2
  • \$\begingroup\$ You can save some byte (1 or 2) by changing your try catch into a if(s.length()>1){...}else \$\endgroup\$
    – AxelH
    Oct 11, 2016 at 11:13
  • \$\begingroup\$ and change the p==1 into p<2 \$\endgroup\$
    – AxelH
    Oct 11, 2016 at 11:29
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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

\$\endgroup\$
1
  • \$\begingroup\$ You can save bytes: replace foreach by lmap; returnby set x. This is what I can say on a quick glance. \$\endgroup\$
    – sergiol
    Feb 15, 2017 at 2:08
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
  • \$\begingroup\$ Nice to see a PHP entry explained in detail :) \$\endgroup\$
    – Emigna
    Oct 10, 2016 at 21:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.