29
\$\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\$
  • \$\begingroup\$ Is there any restrictions on what characters the string will contain? \$\endgroup\$ – GamrCorps Feb 22 '16 at 18:01
  • \$\begingroup\$ @GamrCorps Nope, no special restrictions. \$\endgroup\$ – Doorknob Feb 22 '16 at 18:06
  • 1
    \$\begingroup\$ Are there any restrictions on the length of the output string? \$\endgroup\$ – Mego Feb 22 '16 at 18:43
  • \$\begingroup\$ @Mego None aside from natural limits imposed by memory/storage. \$\endgroup\$ – Doorknob Feb 22 '16 at 19:58
  • 1
    \$\begingroup\$ HA! This is the undo mechanism in my text editor :D \$\endgroup\$ – slebetman Feb 23 '16 at 2:45

15 Answers 15

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\$
14
\$\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\$
  • \$\begingroup\$ Whats the 2::5 trick? How does that join a string? Isn't that every 5th index starting at 2? \$\endgroup\$ – Robert Fraser Feb 29 '16 at 12:35
  • \$\begingroup\$ @RobertFraser See here. \$\endgroup\$ – xnor Feb 29 '16 at 23:30
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\$
  • \$\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 '16 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 '16 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\$
  • \$\begingroup\$ a=>a.map(([o,s])=>[...s].map(c=>r[o++]=c),r=[])&&r.join`` saves 4 bytes \$\endgroup\$ – edc65 Feb 29 '16 at 8:41
7
\$\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\$
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
    \$\begingroup\$ This answer's a bute! \$\endgroup\$ – Conor O'Brien Feb 22 '16 at 17:44
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\$
  • \$\begingroup\$ Hooray for DUP! \$\endgroup\$ – cat Feb 25 '16 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\$
  • \$\begingroup\$ "Evaling user input is never a good idea" Code Golf is about worst-practices :D \$\endgroup\$ – cat Feb 25 '16 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 '16 at 23:27
  • \$\begingroup\$ Ill try it.. :D \$\endgroup\$ – timmyRS Feb 27 '16 at 7:25
  • \$\begingroup\$ @cat Thx mate, shorted it by 3 chars. :D \$\endgroup\$ – timmyRS Feb 27 '16 at 9:20
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\$
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
\$\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, privacy policy and cookie policy

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