34
\$\begingroup\$

Given an input of a list of slices of a string, output the original string.

Each slice will be given as a list of length 2, containing the start position of the slice (an integer ≥0) and the slice itself. If your language does not support arrays of arbitrary types, you may also take this as a struct or similar, or simply a string consisting of the number, a space, and then the slice.

The order of the two elements of each slice is up to you. Furthermore, if you choose to use the representation of slices as a length-2 array, you may take input as either a 2-dimensional array or a single flat array. Finally, the integer representing position may be either zero-indexed or one-indexed (all the examples here are zero-indexed).

The input will always be sufficient to determine the entire string up to the highest position given. That is, there will be no "holes" or "gaps." Therefore, the output must not contain any extra trailing or leading characters (other than the typical optional trailing newline). The input will always be consistent, and no slices will conflict with each other.

Since this is , the shortest code in bytes will win.

Test cases:

In                                                Out
-----------------------------------------------------------
[[2, "CG"], [0, "PP"], [1, "PC"]]               | PPCG
[[0, "foobarbaz"]]                              | foobarbaz
[[0, "foobar"], [6, "baz"]]                     | foobarbaz
[[2, "ob"], [5, "rba"], [0, "fooba"], [8, "z"]] | foobarbaz
[[0, "fo"], [0, "fooba"], [0, "foobarbaz"]]     | foobarbaz
\$\endgroup\$
7
  • \$\begingroup\$ Is there any restrictions on what characters the string will contain? \$\endgroup\$
    – GamrCorps
    Feb 22, 2016 at 18:01
  • \$\begingroup\$ @GamrCorps Nope, no special restrictions. \$\endgroup\$
    – Doorknob
    Feb 22, 2016 at 18:06
  • 1
    \$\begingroup\$ Are there any restrictions on the length of the output string? \$\endgroup\$
    – user45941
    Feb 22, 2016 at 18:43
  • \$\begingroup\$ @Mego None aside from natural limits imposed by memory/storage. \$\endgroup\$
    – Doorknob
    Feb 22, 2016 at 19:58
  • 2
    \$\begingroup\$ HA! This is the undo mechanism in my text editor :D \$\endgroup\$
    – slebetman
    Feb 23, 2016 at 2:45

24 Answers 24

15
\$\begingroup\$

Python 2, 49 bytes

lambda l:`map(max,*[' '*n+s for n,s in l])`[2::5]

First, lines up the strings by padding their offsets with spaces (shown as underscores for clarity)

[[2, "CG"], [0, "PP"], [1, "PC"]] 

__CG
PP
_PC

Then, uses map to zip and take the maximum of each column, which ignores the smaller values of spaces (the smallest printable character) and Nones where some strings were too short.

__CG
PP
_PC

PPCG

Finally, ''.join to a string using the [2::5] trick.

\$\endgroup\$
2
  • \$\begingroup\$ Whats the 2::5 trick? How does that join a string? Isn't that every 5th index starting at 2? \$\endgroup\$ Feb 29, 2016 at 12:35
  • \$\begingroup\$ @RobertFraser See here. \$\endgroup\$
    – xnor
    Feb 29, 2016 at 23:30
8
\$\begingroup\$

Haskell, 57 bytes

import Data.List
map snd.sort.nub.(>>= \(n,s)->zip[n..]s)

Usage example:

*Main> map snd.sort.nub.(>>= \(n,s)->zip[n..]s) $ [(2,"CG"),(0,"PP"),(1,"PC")]
"PPCG"

How it works: make pairs of (index,letter) for every letter of every slice, concatenate into a single list, remove duplicates, sort by index, remove indices.

\$\endgroup\$
8
\$\begingroup\$

Perl, 25

Added +2 for -lp

Get the input from STDIN, e.g.

perl -lp slices.pl
2 CG
0 PP
1 PC

(Close with ^D or ^Z or whatever closes STDIN on your system)

slices.pl:

/ /;$r|=v0 x$`.$'}{*_=r
\$\endgroup\$
2
  • \$\begingroup\$ Wouldn't the null byte instead of v0 save you two bytes (because you could also omit the space before the x)? Edit: Hm, no, when I tried it, I got Can't locate object method "x" via package "2" (or whatever the number is on my first line) for some reason. \$\endgroup\$
    – msh210
    Feb 24, 2016 at 22:17
  • 1
    \$\begingroup\$ Only names like C variables can be unquoted literals. So v0 is the shortest way to get \0 (or a \0 between quotes for a tie in this case due to the extra space) \$\endgroup\$
    – Ton Hospel
    Feb 24, 2016 at 22:24
8
\$\begingroup\$

JavaScript (ES6), 61 bytes

a=>a.map(([o,s])=>[...s].map(c=>r[o++]=c),r=[])&&r.join``

Edit: Saved 4 bytes thanks to @edc65.

\$\endgroup\$
1
  • \$\begingroup\$ a=>a.map(([o,s])=>[...s].map(c=>r[o++]=c),r=[])&&r.join`` saves 4 bytes \$\endgroup\$
    – edc65
    Feb 29, 2016 at 8:41
5
\$\begingroup\$

Jelly, 10 9 bytes

Ḣ0ẋ;Fµ€o/

Try it online!

How it works

Ḣ0ẋ;Fµ€o/  Main link. Input: A (list of pairs)

     µ€    Convert the chain to the left into a link, and apply it to each pair.
Ḣ          Pop the first element.
 0ẋ        Yield a list of that many zeroes.
   ;F      Concatenate the list of zeroes with the popped, flattened pair.
       o/  Reduce the generated lists by logical OR.
           Since all characters are truthy, this overwrites zeroes with characters,
           but never characters with zeroes.
\$\endgroup\$
5
\$\begingroup\$

Factor, 64 40 bytes

[ sbuf new tuck '[ _ copy ] assoc-each ]

Attempt This Online!

This answer makes use of the fact you can set arbitrary indices of a growable sequence (in this case a string buffer) and the sequence will expand appropriately with default values. copy copies one sequence to another starting at an index; a perfect fit for this problem.

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

MATL, 15 bytes

''i"@Y:Y:tn:b+(

Works with current version (13.0.0) of the language/compiler.

Input is with curly braces and single quotes. (Curly braces in MATLAB/MATL define cell arrays, which are lists that can have contents of arbitrary, possibly different types.) The test cases are thus:

{{2, 'CG'}, {0, 'PP'} {1, 'PC'}}
{{0, 'foobarbaz'}}
{{0, 'foobar'}, {6, 'baz'}}
{{2, 'ob'}, {5, 'rba'}, {0, 'fooba'}, {8, 'z'}}
{{0, 'fo'}, {0, 'fooba'}, {0, 'foobarbaz'}}

Try it online!

''      % push empty string. This will be filled with the slices to produce the result
i       % take input: cell array of cell arrays. For example: {{0, 'foobar'}, {6, 'baz'}}
"       % for each (1st-level) cell
  @     %   push that cell. Example: {{0, 'foobar'}}
  Y:    %   unpack (1st-level) cell, i.e. push its contents. Example: {0, 'foobar'}
  Y:    %   unpack (2nd-level) cell array: gives number and substring. Example: 0, 'foobar'
  tn:   %   duplicate substring and generate vector [1,2,...,n], where n is length of
        %   current substring (in the example: 6)
  b+    %   add input number that tells the position of that substring within the whole
        %   string (in the example: 0; so this gives [1,2,...,6] again)
  (     %   assign substring to the total string, overwriting if necessary. Note that
        %   MATL uses 1-indexing
        % end for each
        % implicit display
\$\endgroup\$
1
  • 1
    \$\begingroup\$ This answer's a bute! \$\endgroup\$ Feb 22, 2016 at 17:44
4
\$\begingroup\$

J, 24 bytes

[:u:3>./@u:-@(+#&>){.&>]

Try it online!

alternative, 24 bytes

[:u:[:>./(#&0@[,3 u:])&>

Try it online!

\$\endgroup\$
3
\$\begingroup\$

DUP, 14 bytes

[0[$;$][,1+]#]

Try it here.

Anonymous lambda. Usage:

2"CG"0"PP"1"PC"[0[$;$][,1+]#]!

NOTE: DUP does not really have arrays, so I hope this input format is okay.

Explanation

Well, DUP's string comprehension is... interesting. Strings are stored as a series of number variables, each of which holds a charcode from the string. Something like 2"CG" works as pushing 2 to the stack, then creating a string with index starting from 2.

Because these indexes are really variables, they can be overwritten. That's what the input is really doing: overriding! Try pressing Step on the interpreter site to get a better idea for this. After this, we get an unsliced string.

This is where the outputting comes in.

[            ] {lambda}
 0             {push 0 to the stack as accumulator}
  [   ][   ]#  {while loop}
   $;$         {duplicate, get var at TOS value, see if that var is defined}
        ,1+    {if so, output charcode at TOS and increment accumulator}
\$\endgroup\$
1
  • \$\begingroup\$ Hooray for DUP! \$\endgroup\$
    – cat
    Feb 25, 2016 at 23:22
2
\$\begingroup\$

PHP, 146 chars

Note: Evaling user input is always a good idea.

Golfed

<?$a=[];$f=0;eval("\$b={$argv[1]};");foreach($b as$d){$f=$d[0];$e=str_split($d[1]);foreach($e as$c){$a[$f++]=$c;}}ksort($a);echo join('',$a)."\n";

Ungolfed

<?php
$array = array();
$p = 0;
eval("\$input = {$argv[1]};");
foreach($input as $item)
{
    $p = $item[0];
    $str = str_split($item[1]);
    foreach($str as $part)
    {
        $array[$p++] = $part;
    }
}
ksort($array);
echo join('', $array)."\n";
?>

You can see that I'm just writing the input into an array with the specific key each char has and then output it all.

Tests

php unslice.php '[[0, "foobar"], [6, "baz"]]' -> foobarbaz

php unslice.php '[[2, "CG"], [0, "PP"], [1, "PC"]]' -> PPCG

php shorten.php unslice.php -> Shortened script by 107 chars. :D

\$\endgroup\$
4
  • \$\begingroup\$ "Evaling user input is never a good idea" Code Golf is about worst-practices :D \$\endgroup\$
    – cat
    Feb 25, 2016 at 23:26
  • \$\begingroup\$ $a[$f]=$c;$f++; I don't know PHP but can't this be $a[$f++]=c; ? \$\endgroup\$
    – cat
    Feb 25, 2016 at 23:27
  • \$\begingroup\$ Ill try it.. :D \$\endgroup\$
    – Sainan
    Feb 27, 2016 at 7:25
  • \$\begingroup\$ @cat Thx mate, shorted it by 3 chars. :D \$\endgroup\$
    – Sainan
    Feb 27, 2016 at 9:20
2
\$\begingroup\$

Ruby, 40 bytes

->a{s=""
a.sort.map{s[_1,_2.size]=_2}
s}

Attempt This Online!

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

Vyxal s, 6 bytes

∩÷-∩vG

Try it online! (test suite) Input as a list of [num, str].

Explanation:

∩÷-∩vG # whole program

∩      # transpose (num and str in their own groups)
 ÷     # split into each item
  -    # prepend '-' to str num amount of times (vectorises)
   ∩   # transpose
    v  # for each item (i.e. vectorise next element)
     G # get max char
       # s flag: concatenate list into a string, then print
\$\endgroup\$
2
\$\begingroup\$

Japt -mh, 15 12 bytes

P=úUÎÄ hUÎUÌ

Try it

P=úUÎÄ hUÎUÌ     :Implicit map of each array U in input array W
P=               :Assign to P (an empty string, initially)
  ú              :Right pad P with spaces to length
   UÎ            :  First element of U
     Ä           :  Add 1
       h         :Replace the characters starting at index
        UÎ       :  First element of U
          UÌ     :  With last element of U
                 :Implicit output of last element of resulting array
\$\endgroup\$
1
\$\begingroup\$

Seriously, 48 bytes

,`i@;l(;)+(x@#@k`M;`i@X@M`MMu' *╗`iZi`M`i╜T╗`MX╜

Seriously is seriously bad at string manipulation.

Try it online!

Explanation:

,`i@;l(;)+(x@#@k`M;`i@X@M`MMu' *╗`iZi`M`i╜T╗`MX╜
,                                                 get input
 `              `M;                               perform the first map and dupe
                   `     `MM                      perform the second map, get max element
                            u' *╗                 increment, make string of that many spaces, save in reg 0
                                 `   `M           third map
                                       `    `M    fourth map
                                              X╜  discard and push register 0

Map 1:

i@;l(;)+(x@#@k
i@;l            flatten, swap, dupe string, get length
    (;)+(       make stack [start, end, str]
         x@#@k  push range(start, end), explode string, make list of stack

Map 2:

i@X@M
i@X     flatten, swap, discard (discard the string)
   @M   swap, max (take maximum element from range)

Map 3:

iZi  flatten, zip, flatten (make list of [index, char] pairs)

Map 4:

i╜T╗  flatten, push reg 0, set element, push to reg 0

In a nutshell, this program makes a string with n spaces, where n is the minimum length the string can be based on the input. It determines the index in the result string of each character in each slice, and sets the character in the result string at that index to the character.

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

Python, 91 bytes.

Saved 1 byte thanks to cat.

It's a bit long. I'll golf it down more in a bit.

def f(x):r={j+i:q for(i,s)in x for j,q in enumerate(s)};return"".join(map(r.get,sorted(r)))
\$\endgroup\$
0
1
\$\begingroup\$

Python, 119 115 bytes

def f(x,s=""):
 x.sort()
 for e in x:
  a=e[0];b=e[1]
  for i,c in enumerate(b):
   if len(s)<=(i+a):s+=c
 return s

Test cases

enter image description here

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

Japt, 16 bytes

ñÎrÈ+S hYÌYg)x}P

Try it

Explanation:

ñÎrÈ+S hYÌYg)x}P
               P # Starting with an empty string X
  r           }  # For each item Y in:
ñ                #  Input sorted by 
 Î               #  The first item in each sub-array
   È             # Apply the following to X:
    +S           #  Add a space to the end
       h    )    #  Overwrite:
          Yg     #   Starting index is the first item in Y
        YÌ       #   New characters are the last item in Y
             x   #  Trim any leftover whitespace

Unfortunately h wraps its index, so attempting to write new characters at the end of a string with it instead writes them back at the start.

\$\endgroup\$
1
  • \$\begingroup\$ Sorry, @KamilDrakari, I'd missed that. \$\endgroup\$
    – Shaggy
    Nov 3, 2022 at 15:03
1
\$\begingroup\$

QBasic, 127 114 bytes

INPUT n
FOR j=1TO n
INPUT i
LINE INPUT s$
l=LEN(s$)
e=LEN(r$)-i-l
r$=r$+SPACE$(e*(e<0))
MID$(r$,i+1,l)=s$
NEXT
?r$

You can try it at Archive.org. The input format is: first, the number of slices; then, for each slice, the (0-based) index and the string on separate lines. Here's what running the first test case would look like:

? 3
? 2
CG
? 0
PP
? 1
PC
PPCG

Explanation

INPUT n

Input the number of slices as n.

FOR j = 1 TO n
...
NEXT

Loop n times:

INPUT i

Input the starting index of the next slice as i.

LINE INPUT s$

Input the contents of the slice as s$. LINE INPUT is used to make sure that any printable ASCII character can be included in the input; if characters like , and " could be excluded, the two input statements could be combined as INPUT i,s$, saving 11 bytes.

l = LEN(s$)

Store the length of the slice as l.

e=LEN(r$)-i-l

The result string is stored in r$ (initially empty by default). If merging this slice would extend r$ beyond its current length, the number of characters we would need to add is given by i plus l minus the current length of r$. Calculate this amount, negated (see below for why), and store it as e.

r$ = r$ + SPACE$(e * (e < 0))

Pad r$ as necessary by appending spaces to it. Comparison operators in QBasic return -1 for true and 0 for false. Thus, if e < 0, we append -e spaces; otherwise, we append 0 spaces.

MID$(r$, i + 1, l) = s$

Overwrite l characters of r$, starting at index i + 1 (since MID$ uses 1-based indexing), with the contents of s$.

PRINT r$

After the loop finishes, print the final value of r$.

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

Pyth, 13 bytes

meSd.Tm+*;hde

Test suite

Takes input as a list of elements of the structure [index, string]. Outputs a list of characters.

Explanation:
meSd.Tm+*;hde   | Full code
meSd.Tm+*;hdedQ | with implicit variables
----------------+------------------------------------------------
      m       Q | Map over the input:
       +    ed  |  Prepend the string with
        *;hd    |   <index> spaces
    .T          | Ragged transpose
meSd            | Take the lexicographically last element of each
\$\endgroup\$
1
\$\begingroup\$

05AB1E (legacy), 7 bytes

ε`ú}ζ€à

Output as a list of characters.

Try it online or verify all test cases.

Explanation:

Uses the legacy version of 05AB1E instead of the new one for two reasons:

  1. The zip/transpose builtins work on a list of strings, whereas the new version would require a list of lists of characters.
  2. The minimum/maximum builtins work on characters (using their codepoint), which doesn't work in the new version.
ε     # Map over each pair of the (implicit) input-list:
 `    #  Pop the pair and push both values separated to the list
  ú   #  Pad the string with the integer amount of leading spaces
}ζ    # After the map: zip/transpose the strings, swapping rows/columns, using a default
      # space " " filler if strings are of unequal length
  €   # Map over each string
   à  #  Only leave its maximum character
      # (after which the resulting list of characters is output implicitly)
\$\endgroup\$
0
\$\begingroup\$

CJam, 26 bytes

q~{~0c*\+}%{.{s\s|}}*e_0c-

Try it online!. Takes input in form [["CG"2]["PP"0]["PC"1]].

Explanation:

q~           Read and eval input

{~0c*\+}%    Convert input strings into workable format
{      }%     Map onto each input
 ~            Evaluate
  0c          Null character
    *\+       Multiply by input number and concat to string

{.{s\s|}}*   Combine strings
{       }*    Fold array
 .{    }       Vectorize, apply block to corresponding elements of arrays
   s\s         Convert elements to strings
      |        Set Union

e_0c-        Remove null characters
\$\endgroup\$
0
\$\begingroup\$

R, 181 bytes

n=nchar;m=matrix(scan(,'raw'),ncol=2,byrow=T);w=rep('',max(n(m[,2])+(i<-strtoi(m[,1]))));for(v in 1:nrow(m)) w[seq(i[v]+1,l=n(m[v,2]))]=unlist(strsplit(m[v,2],''));cat("",w,sep="")

With line breaks:

n=nchar
m=matrix(scan(,'raw'),ncol=2,byrow=T)
w=rep('',max(n(m[,2])+(i<-strtoi(m[,1]))))
for(v in 1:nrow(m)) w[seq(i[v]+1,l=n(m[v,2]))]=unlist(strsplit(m[v,2],''))
cat("",w,sep="")

Works in R Gui (single line one, or sourcing for the multi-line one) but not in ideone, example:

> n=nchar;m=matrix(scan(,'raw'),ncol=2,byrow=T);w=rep('',max(n(m[,2])+(i<-strtoi(m[,1]))));for(v in 1:nrow(m)) w[seq(i[v]+1,l=n(m[v,2]))]=unlist(strsplit(m[v,2],''));cat("",w,sep="")
1: 2 ob 5 rba 0 fooba 8 z
9: 
Read 8 items
foobarbaz

Note on the input method:

or simply a string consisting of the number, a space, and then the slice.

I assume I comply with this part of the spec with this kind of input, it can be given on multiple lines, this has no impact as long as there a blank line to end the input.

I think 2 chars can be saved by removing the +1 and using 1 based indexing but I started with challenge input.

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

C, 110 bytes

c,i,j;char s[99];main(){while(~scanf("%i ",&i))for(;(c=getchar())>10;s[i++]=c);for(;s[j]>10;putchar(s[j++]));}

This program takes the slice after its index in one line of input each.

Ungolfed:

c,i,j;char s[99];

main(){
    while(~scanf("%i ",&i))
        for(;(c=getchar())>10;s[i++]=c);
    for(;s[j]>10;putchar(s[j++]));
}

Test on ideone.com

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

Lua, 113 bytes

z=loadstring("return "..io.read())()table.sort(z,function(a,b)return a[1]<b[1]end)for a=1,#z do print(z[a][2])end

This is probably some of the more secure code I've written. The idea is simple. The user will enter an array formatted as so: {{1, "1"}, {3, "3"}, {2, "2"}} and then the table will be sorted by the first index and the second index will be printed.

\$\endgroup\$

Your Answer

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

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