28
\$\begingroup\$

Introduction

For this example, let's take the string Hello, World! and the array [3, 2, 3]. To find the substring chain, we go through the following process:

The first number of the array is 3, so we get the substring [0 - 3], which is Hel. After that, we remove the first 3 characters from the initial string, which leaves us with lo, World!.

The second number of the array is 2, so we get the substring [0 - 2] from our new string, which gives us lo. The leftover string becomes , World!.

The last number is a 3, which gives us , W. The substring chain is all of the substrings combined, which gives us:

['Hel', 'lo', ', W']

For a more visual example:

[3, 2, 3], 'Hello, World!'
3 -> Hel
2 ->    lo
3 ->      , W

The task

Given a non-empty string and a non-empty array only consisting of positive integers (> 0), output the substring chain. You may assume that the sum of all integers in the array does not exceed the length of the string.

You can also assume that the strings will never contain any newlines.

Test cases

Input: abcdefghijk, [2, 1, 3]
Output: ['ab', 'c', 'def']

Input: Code Golf, [4, 1]
Output: ['Code', ' ']

Input: Ayyy, [3]
Output: ['Ayy']

Input: lexicographically, [2, 2, 2, 7, 4]
Output: ['le', 'xi', 'co', 'graphic', 'ally']

This is , so the submission with the smallest number of bytes wins!

\$\endgroup\$
0

33 Answers 33

33
\$\begingroup\$

05AB1E, 1 byte

£

This is the substring(0,N) command.
Applied on a list this works repeatedly on the remainder on the string.

Try it online!

\$\endgroup\$
1
  • 10
    \$\begingroup\$ Can't beat that. \$\endgroup\$
    – Steven H.
    Commented Sep 20, 2016 at 20:50
12
\$\begingroup\$

Python 2, 42 bytes

s,a=input()
for n in a:print s[:n];s=s[n:]

Sometimes you just do it the boring way.

\$\endgroup\$
2
  • \$\begingroup\$ So far the shortest of the far-too-many python answers \$\endgroup\$
    – Cyoce
    Commented Sep 20, 2016 at 22:54
  • \$\begingroup\$ Well apparently I was overthinking it, haha... \$\endgroup\$
    – DJMcMayhem
    Commented Sep 21, 2016 at 4:31
8
\$\begingroup\$

Brachylog, 20 13 bytes

h@[~c.:la~t?,

Try it online!

This is extremely inefficient and times out on TIO for the last test case.

Explanation

Input = [String, List of integers]

h@[            Take a prefix of the string
   ~c.         Take a possible list of strings which when concatenated results in that prefix
      :la      Take the lengths of each element of that list
         ~t?,  This list of lengths is equal to the list of integers of the Input

A slightly more efficient version, 15 bytes

t:{~l}a.,?h@[~c

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

Python 3, 45 bytes

f=lambda s,a:f(s[a[0]:print(s[:a.pop(0)])],a)

This prints one substring per line and terminates with an error when a is exhausted.

Test it on repl.it.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ What a great way to sneak in a print! \$\endgroup\$
    – xnor
    Commented Sep 20, 2016 at 22:20
7
\$\begingroup\$

Python, 52, 46 bytes

f=lambda a,s:a and[s[:a[0]]]+f(a[1:],s[a[0]:])

A recursive lambda function.

Thanks to Dennis for shaving off 6 bytes!

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

Jelly, 6 bytes

Jx$ĠịY

Try it online!

        The implicit working value is the first argument.
Jx$     Given a list L, repeat (x) an element of [1..len(n)] (J)
        as many times as the corresponding value in L.
   Ġ    Group indices by values. This turns [1, 1, 1, 2, 2, 3, 3]
        into [[1, 2, 3], [4, 5], [6, 7]].
    ị   Index into the second argument.
     Y  Join by newlines.
\$\endgroup\$
5
\$\begingroup\$

Haskell, 34 bytes

s#(a:b)=take a s:drop a s#b
_#_=[]

Usage example: "lexicographically" # [2,2,2,7,4] -> ["le","xi","co","graphic","ally"]

Simple recursion.

Or the boring 29 bytes solution via built-in:

import Data.Lists
splitPlaces
\$\endgroup\$
5
\$\begingroup\$

Ruby, 26 bytes

->w,a{a.map{|n|w.shift n}}

Strings are represented as arrays of characters.

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

PowerShell v2+, 46 bytes

param($a,$b)$b|%{-join$a[$i..($i+=$_-1)];$i++}

Takes input string $a and array $b, loops over $b. Each iteration, does an array slice of $a based on $i (defaults to $null, or 0) and the current number. Needs to do the -1 and $i++ because strings in PowerShell are zero-indexed.

Examples

(The output here is space-separated, because that's the default stringification method for arrays)

PS C:\Tools\Scripts\golfing> @('abcdefghijk',@(2,1,3)),@('Code Golf',@(4,1)),@('Ayyy',@(3)),@('lexicographically',@(2,2,2,7,4))|%{""+$_[0]+" -> "+(.\substring-chainification.ps1 $_[0] $_[1])}
abcdefghijk -> ab c def
Code Golf -> Code  
Ayyy -> Ayy
lexicographically -> le xi co graphic ally
\$\endgroup\$
4
\$\begingroup\$

Perl, 28 bytes

Includes +1 for -n

Run with the input string on STDIN followed by each number on a separate line:

(echo "Hello, World!"; echo 3; echo 2; echo 3) | perl -nE 'say for/(??{"."x<>||"^"})/g'

Just the code:

say for/(??{"."x<>||"^"})/g

The 23 bytes version without ||"^" also sort of works, but prints spurious trailing newlines

"^" can be replaced by $_ if the string does not contain regex meta characters

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

MATL, 8 bytes

ys:)1bY{

Try it online!

Explanation

y    % Implicitly take the two inputs: numerical array, string. Duplicate the array
s    % Sum of the array, say n
:    % Range from 1 to n
)    % Take first n characters of the string
1    % Push 1
b    % Bubble up the original copy of the string to the top
Y{   % Split into pieces of lengths given by the numerical array. The pieces are 
     % stored in a cell array, which is implicitly displayed, one cell per line
     
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 39 38 35 bytes

Saved 3 bytes thanks to ETHproductions:

s=>a=>a.map(v=>s.slice(t,t+=v),t=0)

Example:

//Definition
f=
s=>a=>a.map(v=>s.slice(t,t+=v),t=0)

//Call
f('lexicographically')([2, 2, 2, 7, 4]);

//Output
Array [ "le", "xi", "co", "graphic", "ally" ]


Previous solution:
38 bytes thanks to Huntro:

s=>a=>a.map(v=>s.substr(t,v,t+=v),t=0)

39 bytes:

(s,a)=>a.map(v=>s.substr(t,v,t+=v),t=0)
\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can save one byte by currying \$\endgroup\$
    – Huntro
    Commented Sep 20, 2016 at 20:42
  • 2
    \$\begingroup\$ .slice saves a few bytes: s=>a=>a.map(v=>s.slice(t,t+=v),t=0) \$\endgroup\$ Commented Sep 21, 2016 at 0:11
3
\$\begingroup\$

Batch, 74 bytes

@set/ps=
@for %%i in (%*)do @call echo %%s:~0,%%i%%&call set s=%%s:~%%i%%

I'm beating C? This can't be right! Takes the string on STDIN and the array as command-line arguments.

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

Java, 119 Bytes

String[] substringChainification(String s, int[] i) {
    String[] r = new String[i.length];
    int j = 0, f = 0;
    for (int t : i)
        r[j++] = s.substring(f, f += t);
    return r;
}

Golfed:

String[]s(String s,int[]i){String[]r=new String[i.length];int j=0,f=0;for(int t:i)r[j++]=s.substring(f,f+=t);return r;}

I modified Roman Gräf's answer(https://codegolf.stackexchange.com/a/93992/59935), but i don't have enough rep to comment.

I changed the loop implementation and instead of setting the source string to another substring in every iteration, i just change the indices with which i get the substring.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Welcome to PPCG! Great first post! This is exactly what you should do with a golf suggestion, but not enough rep. \$\endgroup\$
    – Riker
    Commented Sep 21, 2016 at 14:39
  • 1
    \$\begingroup\$ Welcome to PPCG! And I agree with _EasterlyIrk_, great first post. I tried to find something to golf more, but couldn't. Maybe you've already seen it, but you might find Tips for golfing in Java interesting to read. Once again welcome, and enjoy your stay. \$\endgroup\$ Commented Sep 22, 2016 at 8:22
2
\$\begingroup\$

Pyke, 10 bytes

FQR<
Ki?>Q

Try it here!

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

sed (82 + 2 for -rn) 84

s,^,\n,;:l;N;s,\n\n,\n,;:
s,^([^\n]*)\n(.)([^\n]*\n)1,\1\2\n\3,
t;P;s,^[^\n]*,,;tl

The first line of input is the string. Then each line after that is the size of a substring in unary.

Example:

$ cat test.txt:
lexicographically
11
11
11
1111111
1111

$ cat hold | sed -rnf sed.txt
le
xi
co
graphic
ally
\$\endgroup\$
2
\$\begingroup\$

CJam, 11 bytes

lq~{/(ns}/;

Try it online!

Explanation

l    e# Read input string.
q~   e# Read array of lengths and eval.
{    e# For each length...
  /  e#   Split the string into chunks of the given size.
  (  e#   Pull off the first chunk.
  n  e#   Print with linefeed.
  s  e#   Flatten the remaining chunks into a single string again.
}/
;    e# Discard any remainder of the input string.
\$\endgroup\$
2
\$\begingroup\$

C, 81 bytes

i,j;f(s,l,k)char*s;int*l;{for(i=j=0;i<k;){write(1,s+j,l[i]);puts("");j+=l[i++];}}

Because write() output is not buffered any online compiler will have a hard time outputting this.

test.c:

i,j;f(s,l,k)char*s;int*l;{for(i=j=0;i<k;){write(1,s+j,l[i]);puts("");j+=l[i++];}}
main(){
    int l[]={3,2,3};
    f("Hello, World!",l,3);
    int ll[]={2,1,3};
    f("abcdefghijk",ll,3);
    int lll[]={4,1};
    f("Code Golf",lll,2);
    int llll[]={3};
    f("Ayyy",llll,1);
    int lllll[]={2,2,2,7,4};
    f("lexicographically",lllll,5);
}

Output without piping:

Hel
lo
, W
ab
c
def
Code
 
Ayy
le
xi
co
graphic
ally
\$\endgroup\$
1
  • \$\begingroup\$ in ideone compiler l'output of above c program [coping the first function the more hight in the screen] is "Hello, WabcdefCode Ayylexicographically" without "\n"... \$\endgroup\$
    – user58988
    Commented Sep 23, 2016 at 9:12
2
\$\begingroup\$

PHP, 98 Bytes

<?php
$b=$argv[1];foreach(explode(',',$argv[2])as$a){echo(substr($b,0,$a).' ');$b=substr($b,$a);}

Usage:

php chainification.php lexicographically 2,2,2,7,4


Output:

le xi co graphic ally


There's probably a better solution with PHP.

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

PHP, 82 Bytes

<?php for($s=$argv[++$i],$j=-1;$n=$argv[++$i];){for(;$n--;)echo$s[++$j];echo"
";}

Takes input as a string and then a list of numbers, output is separated by new lines. e.g.

php chainify.php lexicographically 2 2 2 7 4

If you're one of those people able to use $argv with -r you can save the 6 bytes used for the opening tag.

\$\endgroup\$
3
  • \$\begingroup\$ I am confused about the use of $argv[++$i]. Why not $argv[1] and $argv[2]? \$\endgroup\$
    – MonkeyZeus
    Commented Sep 21, 2016 at 20:07
  • \$\begingroup\$ Also, using PHP 7.0.2 at sandbox.onlinephpfunctions.com I hit the 3 second time limit \$\endgroup\$
    – MonkeyZeus
    Commented Sep 21, 2016 at 20:11
  • \$\begingroup\$ it's not $argv[2] because we need to iterate through the supiled arguments and it's $argv[++$i] the first time to avoid the need for a ,$i=1 and thus saving 2 bytes. \$\endgroup\$
    – user59178
    Commented Sep 22, 2016 at 8:09
2
\$\begingroup\$

PHP, 63 Bytes

<?foreach($_GET[a]as$p){echo" ".substr($_GET[s],$s,$p);$s+=$p;}

Output as Array 85 Bytes

<?foreach($_GET["a"]as$p){$o[]=substr($_GET["s"],$s,$p);$s+=$p;}echo json_encode($o);
\$\endgroup\$
2
\$\begingroup\$

Rebol, 38 bytes

func[s b][map-each n b[take/part s n]]
\$\endgroup\$
1
\$\begingroup\$

Pyth, 7 bytes

PcwsM._

Takes input separated by newline, with the string unescaped and coming after the array. Try it Online!

Explanation:

     ._  Get all prefixes of Q
   sM    Map sum across each of these prefixes (to get the total indices)
 cw      Split the string at these locations
P        Remove the last "remainder" of the string
\$\endgroup\$
1
\$\begingroup\$

Octave / MATLAB, 31 bytes

@(s,a)mat2cell(s(1:sum(a)),1,a)

This is an anonymous function with inputs s: string; a: numerical array.

Try it at Ideone.

Explanation

This is a port of my MATL answer.

s(1:sum(a))        % Take first n characters of string s, where n is the sum of array a
mat2cell(...,1,a)  % Split into pieces of lengths given by a and store in a cell array
\$\endgroup\$
1
\$\begingroup\$

Java 142 bytes

public static String[]substringChain(String s,int[]i){
  String[]r=new String[i.length];
  for(int j=-1;++j<i.length;){
    r[j]=s.substring(0,i[j]);
    s=s.substring(i[j]);
  }
  return b;
}

Golfed:

String[]s(String s,int[]i){String[]r=new String[i.length];for(int j=-1;++j<i.length;){r[j]=s.substring(0,i[j]);s=s.substring(i[j]);}return b;}
\$\endgroup\$
1
\$\begingroup\$

Awk, 36 characters

{FIELDWIDTHS=$0;OFS=RS;getline}$1=$1

Sample run:

bash-4.3$ awk '{FIELDWIDTHS=$0;OFS=RS;getline}$1=$1' <<< $'3 2 3\nHello, World!'
Hel
lo
, W

In real life I would use it like this, just no idea how to calculate its score:

bash-4.3$ awk -vFIELDWIDTHS='3 2 3' -vOFS='\n' '$1=$1' <<< 'Hello, World!'
Hel
lo
, W
\$\endgroup\$
1
\$\begingroup\$

Dyalog APL 16.0, 15 characters (non-competing); 15.0, 17 bytes

16.0 solution

{⍵⊆⍨(⍴⍵)↑⍺/+\⍺}

Dyalog APL 16.0 adds APL2's partition primitive, , with the glyph .

15.0 solution:

{(-⍺)↑¨(+\⍺)↑¨⊂⍵}

TryAPL online!

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

GNU sed, 55 + 2(rn flags) = 57 bytes

1H;1d;G;:;s=.(\n.*)\n(.)=\1\2\n=;t;s=.==;P;s=[^\n]*==;h

Try it online! (thanks to @Dennis for adding sed)

Explanation: The input string should be on the first line and the numbers, in unary, on separate lines after that. A new line is read implicitly at the start of a cycle, running the script each time.

1H;1d                       # once: append string to hold space and start new cycle
                            #Initially, the hold space contains an useful '\n'.
G                           # append hold space to pattern space. The pattern space
                            #format will be: 'UNARY\n\nSTRING'.
:;s=.(\n.*)\n(.)=\1\2\n=;t  # iteratively remove a char from the string, as many
                            #times as unary chars, and store it on 2nd pattern line
s=.==;P                     # remove '\n', then print the new top line
s=[^\n]*==;h                # delete up to '\n' and update hold space

Test run: using a here-document with EOF as the end marker

sed -rnf program.sed << EOF
> abcdefghijk
> 00
> 0
> 000
> EOF

Output:

ab
c
def
\$\endgroup\$
1
\$\begingroup\$

Ruby, 28 bytes

->a,w{a.map{|e|w.slice!0,e}}

In case arguments are an array of positive integers and one string.

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

Vimscript, 79 78 bytes

not very pretty, I'm sure it can be improved...

Takes a vim buffer, then call echom string(A([2,3])) to see the output

fu A(l)
let r=[]
for i in a:l
exe "norm d".i."l"
let r+=[@"]
endfo
retu r
endf

I actually thought of cheating and outputing the string ["abc", "def"]... But I resisted :P

Explanation: Delete (puts in default register) each array items amounts of characters and adds it to the array r... A boring answer indeed.

\$\endgroup\$

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.