11
\$\begingroup\$

Background

In X11 (a windowing system used by a lot of Unix-like OS), what you would call the clipboard behave a bit differently than on other OSes like MacOS or Windows. While the "traditional" clipboard using ctrl+v/ctrl+c works, there is also another clipboard, called PRIMARY selection, that behave as following:

  • when you select a piece of text, this selection is added to the clipboard
  • when you use the middle mouse button, the content of that selection is pasted where your mouse is.

Some more details for those who are interested : X11: How does “the” clipboard work?

Challenge

The input in this challenge is any representation of a binary input. In the following I will use 'S' for select and 'P' for paste.

Given the input, you must output the input after making the following changes :

  • put the content of the current output in the primary selection when you receive a select instruction
  • paste the content of the primary selection in the middle of the current output when you receive a paste instruction. If the current output is odd numbered, the middle is the length divided by 2 and truncated.

Example

Input is SPSP :

selection = ""
output = "SPSP"
 SPSP
↑
selection = "SPSP"
output = "SPSP"
 SPSP
 ↑
selection = "SPSP"
output = "SPSPSPSP"
 SPSP
  ↑
selection = "SPSPSPSP"
output = "SPSPSPSP"
 SPSP
   ↑
selection = "SPSPSPSP"
output = "SPSPSPSPSPSPSPSP"
 SPSP
    ↑

Final Output is SPSPSPSPSPSPSPSP

Test Cases

"" -> ""
"S" -> "S"
"P" -> "P"
"PS" -> "PS"
"SP" -> "SSPP"
"SPP" -> "SSPSPPPPP"
"SPSP" -> "SPSPSPSPSPSPSPSP"
"SPPSP" -> "SPSPPSPSPSPPSPPSPSPPSPPSPSPPSP"
"SPPSPSSS" -> "SPPSSPPSSPPSSPPSSPPSSPPSPSSSPSSSPSSSPSSSPSSSPSSS"

Reference Implementation

In Python 3 :

def clipboard(inp, select="S", paste="P"):
    out = inp
    primary_selection = ""
    for instruction in inp:
        if instruction is select:
            primary_selection = out
        if instruction is paste:
            out = out[:len(out)//2] + primary_selection + out[len(out)//2:]
    return out

Try it online!

Rules

  • You may assume that the input contains only the "paste" or "select" characters (you don't need to handle error cases)
  • You may take your input newline separated (e.g S\n P\n S\n)
  • You may use any kind of data representation (e.g binary data,\n(newline) as a select character and (space) as a paste character, etc.)
  • Standard rules , shortest submission by bytes wins!
\$\endgroup\$
2
  • 7
    \$\begingroup\$ Alternative question title: get your cat's attention \$\endgroup\$ – Razetime Dec 12 '20 at 3:27
  • 1
    \$\begingroup\$ @Razetime only if this question had to do something with cat programs... You probably should think of one, then! \$\endgroup\$ – val is still with Monica Dec 12 '20 at 19:17
4
\$\begingroup\$

Python 2, 64 59 bytes

Input is a list of integers, 0 for select and 1 for paste. Outputs by modifying the input list.

def c(o,p=[]):
 for y in o*1:p=[o*1,p][y];o[len(o)/2:0]=p*y

Try it online!

Commented:

def c(o, p=[]):
    # o is the current output, p the current clipbord value
    # Iterate over a copy of the input list
    for y in o*1:
        # If y==0 (select) assign a copy of o to p
        p=[o*1,p][y]
        # Replace the empty slice at index len(o)/2 with:
        #  - a copy of p if y==1 (paste)
        #  - an empty list otherwise
        o[len(o)/2:0]=p*y

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Nice solution! I really like that creative use of integer inputs. \$\endgroup\$ – Lescurel Dec 12 '20 at 10:01
4
\$\begingroup\$

JavaScript (ES6), 80 bytes

f=(s,[c,...a]=(p='')+s)=>c?f(c<'S'?s.slice(0,i=s.length/2)+p+s.slice(i):p=s,a):s

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ @Giuseppe Thanks for reporting this. This version was actually completely wrong. \$\endgroup\$ – Arnauld Dec 11 '20 at 18:44
  • 2
    \$\begingroup\$ At least you had a version that worked; I can't tell you how many times I've had to shamefully delete an answer because I posted complete garbage :-) \$\endgroup\$ – Giuseppe Dec 11 '20 at 18:45
4
\$\begingroup\$

Ruby 2.7 -pl, 61 51 47 bytes

Saved 10 bytes using -pl instead of -nl.
Saved 4 bytes using .chars instead of .each_char, thanks to Dingus!

s=''
$_.chars{_1>?P?s=$_*1:$_.insert(~/$//2,s)}

Try it online!

TIO uses an older version of Ruby, whereas in Ruby 2.7, we've numbered parameters, i.e., _1, which saves 2 bytes.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ You can use chars instead of each_char. $_*1 is really nice by the way - I hadn't seen that method of duping before. \$\endgroup\$ – Dingus Dec 12 '20 at 9:47
  • \$\begingroup\$ @Dingus - Thanks! I was trying * oper and it worked. I guess, I should add this in ruby tips, if it's not there.. \$\endgroup\$ – vrintle Dec 12 '20 at 10:03
  • 1
    \$\begingroup\$ Sadly, it is already there :'-) In fact there is a shorter method a=-b to clone! \$\endgroup\$ – vrintle Dec 12 '20 at 10:20
3
\$\begingroup\$

Perl 5 -nF, 45 bytes

@o=@F;/S/?@,=@o:splice@o,@F/2,0,@,for@F;say@o

Try it online!

Could be shortened by 1 if the input is 0 and 1 instead of S and P.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ The challenge says: "You may use any kind of data representation (e.g binary data,\n(newline) as a select character and (space) as a paste character, etc.)" \$\endgroup\$ – Giuseppe Dec 11 '20 at 18:18
2
\$\begingroup\$

Charcoal, 24 bytes

Fθ≡ιS≔θω≔⪫E⮌⪪⮌θ⊘⊕Lθ⮌κωθθ

Try it online! Link is to verbose version of code. Explanation:

Fθ

Loop over the characters of the input.

≡ιS

If the current character is an S, then...

≔θω

... overwrite the predefined empty string with the current output.

≔⪫E⮌⪪⮌θ⊘⊕Lθ⮌κωθ

Otherwise, insert the selection into the middle of the current output. Curiously, the best way to do this appears to be to reverse the string, split it by half its length rounded up, then reverse everything back again, finally joining the two halves together using the selection.

θ

Print the final output.

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

Retina 0.8.2, 67 bytes

^
¶$'¶
{`.*¶(.+¶)S
$1$1
}`(¶(.)*)((?<-2>.)*(?(2)$).*¶)P
$1$`$3
2=G`

Try it online! Link includes test cases. Explanation:

^
¶$'¶

Insert a blank line representing the clipboard and a copy of the input which becomes the output.

{`
}`

Repeat until all of the input has been processed.

.*¶(.+¶)S
$1$1

If the next character in the input is an S then copy the output to the clipboard.

(¶(.)*)((?<-2>.)*(?(2)$).*¶)P
$1$`$3

But if it's a P then insert the clipboard into the middle of the output.

2=G`

Keep just the final output.

\$\endgroup\$
1
  • \$\begingroup\$ Although Retina 1 has dynamic elements, and can therefore port @ovs's Python 2 answer, I couldn't get that version to fewer than 76 bytes. \$\endgroup\$ – Neil Dec 11 '20 at 21:11
2
\$\begingroup\$

SNOBOL4 (CSNOBOL4), 119 bytes

	O =I =INPUT
N	I LEN(1) $ X REM . I	:F(O)S($X)
S	S =O	:(N)
P	O LEN(SIZE(O) / 2) $ L REM $ R =L S R	:(N)
O	OUTPUT =O
END

Try it online!

	O =I =INPUT					;* Read input and set O to it as well
N	I LEN(1) $ X REM . I	:F(O)S($X)		;* Next character:get the first character of I and set the REMainder to I
							;* if there are no characters left, goto O
							;* else goto the value of X
S	S =O	:(N)					;* on S: set S to O and goto N
P	O LEN(SIZE(O) / 2) $ L REM $ R =L S R	:(N)	;* on P: get the first (left) half of O and set to L,
							;* set the REMainder (right half) to R, and replace with L S R,
							;* then goto N
O	OUTPUT =O					;* output O
END
\$\endgroup\$
1
\$\begingroup\$

Ruby, 99 bytes

->a{s="";(o=a).chars{|n|(n==?S)?s=o:o=o.chars.each_slice((o.size*0.5).ceil).map(&:join).join(s)};o}

Try it online!

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

05AB1E, 16 bytes

vy'SQi©ëR2äRí®ýá

Try it online or verify all test cases.

Explanation:

v              # Loop `y` over each character of the (implicit) input-string
 y'SQi        '#  If the current `y` is equals to "S":
      ©        #   Store the current string in variable `®`
               #   (which will use the implicit input with the first occurrence of "S")
     ë         #  Else:
      R        #   Reverse the current string
       2ä      #   Split it into two equal-sized parts
               #   (where the first part is longer for odd lengths; hence the reverse)
         Rí    #   Reverse the pair, and each individual string back
           ®ý  #   Join it by `®`
             á #   And only leave the letters in the string
               #   (`®` is -1 by default, so this'll remove it for inputs starting with a "P")
               # (after the loop, the result is output implicitly)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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