20
\$\begingroup\$

Given an ASCII string, output the exploded suffixes of it. For example, if the string was abcde, there are 5 suffixes, ordered longest to shortest:

abcde
bcde
cde
de
e

Each suffix is then exploded, meaning each character is copied as many times as its one-indexed location in that suffix. For example, exploding the suffixes of abcde,

abcde
12345
abbcccddddeeeee

bcde
1234
bccdddeeee

cde
123
cddeee

de
12
dee

e
1
e

Altogether, the exploded suffixes of abcde are

abbcccddddeeeee
bccdddeeee
cddeee
dee
e

Rules

  • This is so the shortest code wins.
  • The input will consist of the printable ASCII characters. (This excludes newlines but includes spaces.)
  • The output will have each string on a separate line.
  • Trailing spaces are allowed on each line and there may be an extra newline at the end.

Test Cases

''

'a'
a

'bc'
bcc
c

'xyz'
xyyzzz
yzz
z

'code-golf'
coodddeeee-----ggggggooooooollllllllfffffffff
oddeee----gggggoooooolllllllffffffff
dee---ggggooooollllllfffffff
e--gggoooolllllffffff
-ggooollllfffff
goolllffff
ollfff
lff
f

's p a c e'
s  ppp    aaaaa      ccccccc        eeeeeeeee
 pp   aaaa     cccccc       eeeeeeee
p  aaa    ccccc      eeeeeee
 aa   cccc     eeeeee
a  ccc    eeeee
 cc   eeee
c  eee
 ee
e
\$\endgroup\$

25 Answers 25

14
\$\begingroup\$

Jelly, 5 bytes

ṫJxJY

Try it online! or verify all test cases.

How it works

ṫJxJY  Main link. Argument: s (string)

 J     Indices; yield I := [1, ..., len(s)].
ṫ      Tail; get the suffixes of s starting at indices [1, ..., len(s)].
   J   Indices; yield I again.
  x    Repeat. The atom 'x' vectorizes at depth 1 (1D arrays of numbers/characters)
       in its arguments. This way, each suffix t gets repeated I times, meaning
       that the first character of t is repeated once, the second twice, etc.
       If left and right argument have different lengths, the longer one is
       truncated, so I can safely be applied to all suffixes.
    Y  Join, separating by linefeeds.
\$\endgroup\$
8
\$\begingroup\$

J, 22 12 8 bytes

Thanks to miles for saving 14 bytes!

(#~#\)\.

Now this is a really nice solution. Pretty succinct, too.

This is the hook #~#\ applied to the suffixes (\.) of the input. The hook, when called on input y, is decomposed as thus:

(#~#\) y
y #~ #\ y

Here are some intermediate results:

   ]s =: 's p a c e'
s p a c e
   #\ s
1 2 3 4 5 6 7 8 9
   (quote) s
's p a c e'
   (quote;#)\ s
+-----------+-+
|'s'        |1|
+-----------+-+
|'s '       |2|
+-----------+-+
|'s p'      |3|
+-----------+-+
|'s p '     |4|
+-----------+-+
|'s p a'    |5|
+-----------+-+
|'s p a '   |6|
+-----------+-+
|'s p a c'  |7|
+-----------+-+
|'s p a c ' |8|
+-----------+-+
|'s p a c e'|9|
+-----------+-+
   1 2 3 # '123'
122333
   3 3 3 # '123'
111222333
   ]\. s
s p a c e
 p a c e
p a c e
 a c e
a c e
 c e
c e
 e
e
   quote\. s
's p a c e'
' p a c e'
'p a c e'
' a c e'
'a c e'
' c e'
'c e'
' e'
'e'
   (#~#\) s
s  ppp    aaaaa      ccccccc        eeeeeeeee
   (#~#\)\. s
s  ppp    aaaaa      ccccccc        eeeeeeeee
 pp   aaaa     cccccc       eeeeeeee
p  aaa    ccccc      eeeeeee
 aa   cccc     eeeeee
a  ccc    eeeee
 cc   eeee
c  eee
 ee
e

Test cases

   f =: (#~#\)\.
   f
(#~ #\)\.
   f ''
   f 'a'
a
   f 'bc'
bcc
c
   f 'xyz'
xyyzzz
yzz
z
   f 'code-golf'
coodddeeee-----ggggggooooooollllllllfffffffff
oddeee----gggggoooooolllllllffffffff
dee---ggggooooollllllfffffff
e--gggoooolllllffffff
-ggooollllfffff
goolllffff
ollfff
lff
f
   f 's p a c e'
s  ppp    aaaaa      ccccccc        eeeeeeeee
 pp   aaaa     cccccc       eeeeeeee
p  aaa    ccccc      eeeeeee
 aa   cccc     eeeeee
a  ccc    eeeee
 cc   eeee
c  eee
 ee
e

   ]tc =: <;._1 '|' , '|a|bc|xyz|code-golf|s p a c e'
++-+--+---+---------+---------+
||a|bc|xyz|code-golf|s p a c e|
++-+--+---+---------+---------+
   ,. f &. > tc
+---------------------------------------------+
+---------------------------------------------+
|a                                            |
+---------------------------------------------+
|bcc                                          |
|c                                            |
+---------------------------------------------+
|xyyzzz                                       |
|yzz                                          |
|z                                            |
+---------------------------------------------+
|coodddeeee-----ggggggooooooollllllllfffffffff|
|oddeee----gggggoooooolllllllffffffff         |
|dee---ggggooooollllllfffffff                 |
|e--gggoooolllllffffff                        |
|-ggooollllfffff                              |
|goolllffff                                   |
|ollfff                                       |
|lff                                          |
|f                                            |
+---------------------------------------------+
|s  ppp    aaaaa      ccccccc        eeeeeeeee|
| pp   aaaa     cccccc       eeeeeeee         |
|p  aaa    ccccc      eeeeeee                 |
| aa   cccc     eeeeee                        |
|a  ccc    eeeee                              |
| cc   eeee                                   |
|c  eee                                       |
| ee                                          |
|e                                            |
+---------------------------------------------+
\$\endgroup\$
  • \$\begingroup\$ Cool, another way to save some bytes is by using the prefix adverb \$\endgroup\$ – miles Oct 15 '16 at 1:16
  • \$\begingroup\$ @miles what do you mean? \$\endgroup\$ – Conor O'Brien Oct 15 '16 at 1:25
  • \$\begingroup\$ You can get the length of each prefix as a shorter way of generating that range \$\endgroup\$ – miles Oct 15 '16 at 1:41
  • \$\begingroup\$ @miles Ah, of course. \$\endgroup\$ – Conor O'Brien Oct 15 '16 at 1:55
7
\$\begingroup\$

Python, 61 bytes

f=lambda s,i=0:s[i:]and-~i*s[i]+f(s,i+1)or s and'\n'+f(s[1:])

Alternative 63:

f=lambda s,b=1:s and f(s[:-1],0)+s[-1]*len(s)+b*('\n'+f(s[1:]))
\$\endgroup\$
6
\$\begingroup\$

Python 3, 91 68 65 bytes

def f(s):f(s[1:print(''.join(i*c for i,c in enumerate(s[0]+s)))])

Terminates with an error after printing the desired output. Test it on Ideone.

How it works

Before f can call itself recursively, the indices of s[1:...] have to be computed.

First enumerate(s[0]+s) yields all pairs (i, c) of characters c of s – with its first character duplicated – and the corresponding indices i. Prepending s[0] serves two purposes here.

  • The first character of s has to be repeated once, but the first index is 0.

  • Once all characters have been processed, s[0] will raise an IndexError, causing f to terminate with an error rather than printing newlines until the recursion limit is reached.

''.join(i*c for i,c in ...) builds a flat string of each c repeated i times, which print echoes to STDOUT.

Finally, since print returns None and s[1:None] is simply s[1:], the recursive call f(s[1:...]) repeats the above process for s without its first character.

\$\endgroup\$
6
\$\begingroup\$

Perl 6, 38 bytes

m:ex/.+$/.map:{put [~] .comb Zx 1..*}

37 bytes + 1 for -n command line switch

Example:

$ perl6 -ne 'm:ex/.+$/.map:{put [~] .comb Zx 1..*}' <<< 'code-golf'
coodddeeee-----ggggggooooooollllllllfffffffff
oddeee----gggggoooooolllllllffffffff
dee---ggggooooollllllfffffff
e--gggoooolllllffffff
-ggooollllfffff
goolllffff
ollfff
lff
f

Expanded:

# -n command line switch takes each input line and places it in 「$_」

# You can think of it as surrounding the whole program with a for loop
# like this:
for lines() {

  # match
  m
  :exhaustive # every possible way
  / .+ $/     # at least one character, followed by the end of the string

  .map:

  {
    put           # print with newline
      [~]         # reduce using string concatenation ( don't add spaces between elements )
        .comb     # split into individual chars
        Z[x]      # zip using string repetition operator
        1 .. *    # 1,2,3,4 ... Inf
  }

}
\$\endgroup\$
5
\$\begingroup\$

Brachylog, 17 bytes

@]Elyk:Erz:jac@w\

Try it online!

Explanation

@]E                 E is a suffix of the Input
   lyk              The list [0, ..., length(E) - 1]
      :Erz          The list [[0th char of E, 0], ..., [Last char of E, length(E) - 1]]
          :ja       For all elements of that list, concatenate the Ith char I times to itself
             c      Concatenate the list into a string
              @w    Write followed by a line break
                \   False: backtrack to another suffix of the Input
\$\endgroup\$
4
\$\begingroup\$

05AB1E, 13 bytes

.sRvyvyN>×}J,

Try it online!

Explanation

.s              # push list of suffixes of input
  R             # reverse the list
   vy           # for each string
     vy   }     # for each char in string
       N>×      # repeat it index+1 times
           J,   # join and print with newline
\$\endgroup\$
4
\$\begingroup\$

CJam, 14 bytes

Sl+{_eee~n1>}h

Try it online!

Explanation

Sl+   e# Read input and prepend a space.
{     e# While the string is non-empty...
  _   e#   Make a copy.
  ee  e#   Enumerate. Gives, e.g. [[0 ' ] [1 'a] [2 'b] [3 'c]].
  e~  e#   Run-length decode. Gives "abbccc".
  n   e#   Print with trailing linefeed.
  1>  e#   Discard first character.
}h
\$\endgroup\$
4
\$\begingroup\$

C#, 101 bytes

f=s=>{var r="\n";for(int i=0;i<s.Length;)r+=new string(s[i],++i);return""==s?r:r+f(s.Substring(1));};

Recursive anonymous function, which also prints a leading newline. If the leading newline is not allowed, 3 extra bytes turn it into a trailing newline:

f=s=>{var r="";for(int i=0;i<s.Length;)r+=new string(s[i],++i);return""==s?r:r+"\n"+f(s.Substring(1));};

Full program with ungolfed method and test cases:

using System;

namespace ExplodedSuffixes
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<string, string> f = null;
            f = s =>
            {
                var r = "\n";
                for (int i = 0; i < s.Length; )
                    r += new string(s[i], ++i);
                return "" == s ? r : r + f(s.Substring(1));
            };

            // test cases:
            string x = "abcde";
            Console.WriteLine("\'" + x + "\'" + f(x));
            x = "";
            Console.WriteLine("\'" + x + "\'" + f(x));
            x = "a";
            Console.WriteLine("\'" + x + "\'" + f(x));
            x = "bc";
            Console.WriteLine("\'" + x + "\'" + f(x));
            x = "xyz";
            Console.WriteLine("\'" + x + "\'" + f(x));
            x = "code-golf";
            Console.WriteLine("\'" + x + "\'" + f(x));
            x = "s p a c e";
            Console.WriteLine("\'" + x + "\'" + f(x));
        }
    }
}
\$\endgroup\$
4
\$\begingroup\$

Haskell, 48 bytes

e=map(concat.zipWith replicate[1..]).scanr(:)[] 

is interfaced by any of

ghc exploded_suffixes.hs -e 'e"abcde"'
ghc exploded_suffixes.hs -e 'mapM_ putStrLn.e=<<getLine' <<<code-golf
ghc exploded_suffixes.hs -e 'Control.Monad.forever$putStr.unlines.e=<<getLine'
\$\endgroup\$
  • \$\begingroup\$ I like the pointfree-ness. You should put your 63-byte code in its own block and then show the invocation separately. \$\endgroup\$ – xnor Oct 15 '16 at 2:25
  • \$\begingroup\$ You don't need putStr., we accept as function output. You do need to import Data.List though to use tails. \$\endgroup\$ – xnor Oct 15 '16 at 2:34
  • \$\begingroup\$ You can replace uncurry ... zip with zipWith: unlines.map(concat.zipWith replicate[1..]).tails. \$\endgroup\$ – nimi Oct 15 '16 at 9:42
  • \$\begingroup\$ Yes indeed! The zipWith replicate shorten also occured to me when i awoke. Pity that tails is not in Prelude i could fetch tails from Data.List implicitly without a full import and still without outgrowing the foldr equivalent. Regarding purity without IO boiler-plate i would also leave the mapM_ putStrLn seasoning to readers' tastes and perform no unlines either. Defining a block e= would cost byte count. \$\endgroup\$ – Roman Czyborra Oct 15 '16 at 14:38
  • \$\begingroup\$ Using qualified names without imports is not standard Haskell, but a feature of the ghci repl. Depending on such things counts as a separate language, so I suggest to change the title of your answer to something like Haskell (ghci). (See also this meta discussion ). \$\endgroup\$ – nimi Oct 15 '16 at 23:13
3
\$\begingroup\$

Perl, 36 + 1 (-n) = 37 bytes

/.+$(?{$.=say$&=~s%.%$&x$.++%rge})^/

Needs -n and -E (or -M5.010) to run :

perl -nE '/.+$(?{$.=say$&=~s%.%$&x$.++%rge})^/' <<< "code-golf"

Note that it works on only one instance each time you run it (because it uses the variable $. which is incremented every time a line is read, so it hold 1 only the first time a line is read). (But no problem here, just ^D and re-run it!)

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

Retina, 31 bytes

Byte count assumes ISO 8859-1 encoding.

M&!`.+

$.%`$*»
%+r`»($|.)
$1$1

Try it online!

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

Java, 150 127 bytes

Edit:

  • -23 bytes off. Thanks to @Kevin Cruijssen

Snipet:

f->{String s[]=f.split(""),o="";int i=-1,j,l=s.length;for(;++i<l;)for(j=-2;++j<i;o+=s[i]);return l<1?"":o+"\n"+f.substring(1);}

Ungolfed:

public static String explodeSuff(String suff){
  char [] s = suff.toCharArray();
  String out = "";
  if(s.length==0)return "";
  for(int i=-1;++i<s.length;){
    for(int j=-2;++j<i;){
      out+=s[i];
    }
  }
  return out+"\n"+suff.subString(1);
}
\$\endgroup\$
  • \$\begingroup\$ Hi, you can golf it quite a bit simply by removing spaces and some small tricks: f->{String s[]=f.split(""),o="";int i=-1,j,l=s.length;for(;++i<l;)for(j=-2;++j<i;o+=s[i]);return l<1?o:o+"\n"+f.substring(1);} \$\endgroup\$ – Kevin Cruijssen Oct 17 '16 at 9:16
2
\$\begingroup\$

Racket 184 bytes

(let p((l(string->list s))(ol'()))(cond[(null? l)(display(list->string(flatten ol)))]
[else(p(cdr l)(append ol(list #\newline)(for/list((i l)(n(length l)))(for/list((j(+ 1 n)))i))))]))

Ungolfed:

(define(f s)
 (let loop((l(string->list s))
             (outl '()))
    (cond
      [(null? l)
       (display
        (list->string
         (flatten outl)))]
      [else
       (loop
        (rest l)
        (append outl
                (list #\newline)
                (for/list ((i l)
                           (n (length l)))
                  (for/list ((j (add1 n)))
                    i
                    ))))]  )))


(f "abcde")
(f "xyz")

Output:

abbcccddddeeeee
bccdddeeee
cddeee
dee
e

xyyzzz
yzz
z
\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 65 bytes

f=s=>s?[s.replace(/./g,(c,i)=>c.repeat(i+1)),...f(s.slice(1))]:[]
<input oninput=o.textContent=f(this.value).join`\n`><pre id=o>

Previous attempts:

67: s=>[...s].map((_,i)=>s.slice(i).replace(/./g,(c,i)=>c.repeat(i+1)))
84: s=>s.replace(/./g,`$&$'
    `).match(/.+/g).map(s=>s.replace(/./g,(c,i)=>c.repeat(i+1)))
89: f=(s,t=s.replace(/./g,(c,i)=>c.repeat(i+1)))=>t?[]:[t,...f(s,t.replace(/(.)(?=\1)/g,''))]
\$\endgroup\$
2
\$\begingroup\$

PHP, 103 bytes (99 with short tags)

<?php for($s=$argv[1];""!=$s[$i++];$o.="
")for($j=0;""!=$l=$s[$j+$i-1];)$o.=str_pad('',++$j,$l);echo$o;

I'm pretty certain this isn't the shortest possible answer.

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

MATL, 12 bytes

&+gYRYs"G@Y"

I love it when quote marks come together!

Try it online!

Explanation

This works by building a matrix whose columns are used, one by one, to run-length decode the input. As an example, for input 'abcde' the matrix is

1 0 0 0 0
2 1 0 0 0
3 2 1 0 0
4 3 2 1 0
5 4 3 2 1

Code:

&+g    % Implicit input. NxN matrix of ones, where N is input size
YR     % Set entries above diagonal to zero
Ys     % Cumulative sum of each column. This gives the desired matrix 
"      % For each column
  G    %   Push input (for example 'abcde')
  @    %   Push current column (for example [0;0;1;2;3])
  Y"   %   Run-length decode (example output 'cddeee')
       % Implicit end
       % Implicit display
\$\endgroup\$
1
\$\begingroup\$

Python 3, 95 bytes

def f(s):return'\n'.join(''.join(s[j:][i]*(i+1)for i in range(len(s)-j))for j in range(len(s)))

This was surprisingly harder than I expected it to be. I redid my whole function maybe 4 times.

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

Java 7,140 bytes

void c(char[]a,int l,int j){if(l<1)return;c(a,--l,++j);for(int i=0,k;i<j;i++)for(k=0;k++<=i;)System.out.print(a[i+l]);System.out.println();}

Ungolfed

 void c(char[]a,int l,int j)
{
if (l < 1) 
return ;
c(a , --l , ++j) ;
for(int i = 0 , k; i < j ; i++)
for(k = 0 ; k++ <= i ;)
System.out.print(a[i+l]);
System.out.println();
}

Following line giving me very pain.i don't know how can i golfed it(because there are two loops to break the condition to put "\n" in print statement).
System.out.println();

\$\endgroup\$
  • \$\begingroup\$ How about a proper method which doesn't require sending the array length too as an argument? Currently one can trigger an IndexOutOfBounds exception by sending a wrong value accidentally... \$\endgroup\$ – adrianmp Oct 16 '16 at 11:12
1
\$\begingroup\$

Pyke, 12 bytes

VilS],A*s
}t

Try it here!

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

Ruby, 51 bytes

Uses the -n flag for +1 byte.

(k=0;puts$_.gsub(/./){$&*k+=1};$_[0]="")while$_>$/
\$\endgroup\$
1
\$\begingroup\$

R, 108 bytes

Read input from stdin and prints to stdout

s=scan(,"");n=nchar(s);for(i in 1:n)cat(do.call("rep",list(strsplit(s,"")[[1]][i:n],1:(n-i+1))),"\n",sep="")

I felt the use of do.call was appropriate here. It basically takes two inputs: 1. a function name in form of a string (rep here) and a list of arguments and 2. iteratively applies calls the function using the arguments in the list.

E.g.:

  • rep("c",3) produces the vector "c" "c" "c"
  • do.call("rep",list(c("a","b","c"),1:3)) produces the vector "a" "b" "b" "c" "c" "c"
  • which is equivalent to consecutively calling rep("a",1), rep("b",2) and rep("c",3)
\$\endgroup\$
1
\$\begingroup\$

Vim, 43 bytes

qqYlpx@qq@qqr0<C-H><C-V>{$:s/\v%V(.)\1*/&\1/g<CR>@rq@r

First macro separates the suffixes, second macro "explodes" them. Likely beatable. Spaces are annoying.

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

C, 186 Bytes

#include <string.h>
#define S strlen
p(char* s){char *t=s;char u[999]="";for(int i=0;i<S(s);i++){for(int j=i+1;j>0;j--){sprintf(u+S(u),"%c",*t);}t++;}printf("%s\n",u);if(S(s)>1)p(s+1);}

This probably can be shortened quite a bit, but I just wanted to try it. It's my second try at golf, so give me any pointers (*lol) you can. It takes a string as a parameter and does the exploding from there. u is used as a buffer that stores the exploded string.

Ungolfed:

#include <string.h>
#define S strlen 
p(char* s){
    char *t=s;
    char u[999]="";
    for(int i=0;i<S(s);i++){
        for(int j=i+1;j>0;j--){
            sprintf(u+S(u),"%c",*t);
        }
        t++;
    }
    printf("%s\n",u);
    if(S(s)>1)p(s+1);
}
\$\endgroup\$
1
\$\begingroup\$

Acc!!, 150 bytes

Expects input on stdin, terminated with a tab character.

N
Count c while _/128^c-9 {
_+N*128^(c+1)
}
Count i while _-9 {
Count j while _/128^j-9 {
Count k while j+1-k {
Write _/128^j%128
}
}
Write 10
_/128
}

Explanation

This is actually a pretty good task for Acc!!, since it only requires reading a string and iterating over it with some nested loops. We read the string into the accumulator, treating it as a sequence of base-128 digits, with the first character on the low-order end. After the opening Count c loop, the accumulator value can be conceptualized like this (using xyz as example input):

128^   3  2  1  0
     tab  z  y  x

(The actual accumulator value for this example is 9*128^3 + 122*128^2 + 121*128 + 120 = 20888824.)

We can then iterate over the string by iterating over increasing powers of 128. And we can iterate over the suffixes by dividing the accumulator by 128 after each iteration, chopping off a character.

With indentation and comments:

# Initialize the accumulator with the first input character
N
# Loop until most recent input was a tab (ASCII 9)
Count c while _/128^c - 9 {
    # Input another character and add it at the left end (next higher power of 128)
    _ + N * 128^(c+1)
}

# Loop over each suffix, until only the tab is left
Count i while _ - 9 {
    # Loop over powers of 128 until the tab
    Count j while _/128^j - 9 {
        # Loop (j+1) times
        Count k while j + 1 - k {
            # Output the j'th character
            Write _ / 128^j % 128
        }
    }
    # Output a newline
    Write 10
    # Remove a character
    _/128
}
\$\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.