39
\$\begingroup\$

Introduction:

Inspired by this comment of @MagicOctopusUrn on @Emigna's 05AB1E answer for my "It was just a bug" challenge:

8F9ÝÀNð×ý}».∊ I done did made a spaceship maw! And I was all excited about suggesting a 12-byte edit. – Magic Octopus Urn Jul 17 '17 at 20:10

Which is a 05AB1E (legacy) program resulting in this:

1234567890
1 2 3 4 5 6 7 8 9 0
1  2  3  4  5  6  7  8  9  0
1   2   3   4   5   6   7   8   9   0
1    2    3    4    5    6    7    8    9    0
1     2     3     4     5     6     7     8     9     0
1      2      3      4      5      6      7      8      9      0
1       2       3       4       5       6       7       8       9       0
1      2      3      4      5      6      7      8      9      0
1     2     3     4     5     6     7     8     9     0
1    2    3    4    5    6    7    8    9    0
1   2   3   4   5   6   7   8   9   0
1  2  3  4  5  6  7  8  9  0
1 2 3 4 5 6 7 8 9 0
1234567890

Try it online.

Challenge:

Input: A non-empty string

Output: From outwards going inwards, add one more space between each character every line, similar as done in the output above, equal to the length - 1. So for an input 1234567890 the output would actually be this instead:

1234567890
1 2 3 4 5 6 7 8 9 0
1  2  3  4  5  6  7  8  9  0
1   2   3   4   5   6   7   8   9   0
1    2    3    4    5    6    7    8    9    0
1     2     3     4     5     6     7     8     9     0
1      2      3      4      5      6      7      8      9      0
1       2       3       4       5       6       7       8       9       0
1        2        3        4        5        6        7        8        9        0
1         2         3         4         5         6         7         8         9         0
1        2        3        4        5        6        7        8        9        0 
1       2       3       4       5       6       7       8       9       0
1      2      3      4      5      6      7      8      9      0
1     2     3     4     5     6     7     8     9     0
1    2    3    4    5    6    7    8    9    0
1   2   3   4   5   6   7   8   9   0
1  2  3  4  5  6  7  8  9  0
1 2 3 4 5 6 7 8 9 0
1234567890

Why? The length of 1234567890 is 10. So we start by outputting 10 lines: the first line without spaces; second with one space delimiter; third with two; etc. And then (without have the middle line with length - 1 spaces duplicated), we go back to the initial input while going down.

Challenge rules:

  • Input is guaranteed to be non-empty (a length >= 1). (For single char inputs we simply output that character.)
  • Any amount of trailing/leading spaces/newlines are allowed, as long as the output itself (wherever on the screen) is correct. (Empty line(s) in between output lines also isn't allowed.)
  • Input will only contain printable ASCII characters excluding whitespaces (code-point range [33, 126])
  • I/O is flexible. Input may be taken as STDIN, argument, or function parameter. May be a list/array/stream of characters instead of string. Output may also be a list/array/stream of characters instead of strings; may be printed to STDOUT; returned as newline-delimited string; etc.

General rules:

  • This is , so shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code.
  • Also, adding an explanation for your answer is highly recommended.

Test cases:

Input: @
Output:
@

Input: test
Output:
test
t e s t
t  e  s  t
t   e   s   t
t  e  s  t
t e s t
test

Input: ?!
Output:
?!
? !
?!

Input: Spaceship
Output:
Spaceship
S p a c e s h i p
S  p  a  c  e  s  h  i  p
S   p   a   c   e   s   h   i   p
S    p    a    c    e    s    h    i    p
S     p     a     c     e     s     h     i     p
S      p      a      c      e      s      h      i      p
S       p       a       c       e       s       h       i       p
S        p        a        c        e        s        h        i        p
S       p       a       c       e       s       h       i       p
S      p      a      c      e      s      h      i      p
S     p     a     c     e     s     h     i     p
S    p    a    c    e    s    h    i    p
S   p   a   c   e   s   h   i   p
S  p  a  c  e  s  h  i  p
S p a c e s h i p
Spaceship

Input: 05AB1E
Output:
05AB1E
0 5 A B 1 E
0  5  A  B  1  E
0   5   A   B   1   E
0    5    A    B    1    E
0     5     A     B     1     E
0    5    A    B    1    E
0   5   A   B   1   E
0  5  A  B  1  E
0 5 A B 1 E
05AB1E

Input: )}/\
Output:
)}/\
) } / \
)  }  /  \
)   }   /   \
)  }  /  \
) } / \
)}/\
\$\endgroup\$
  • 1
    \$\begingroup\$ Gets all just jittery !!!SPACESHIP!!! \$\endgroup\$ – WallyWest Sep 5 '18 at 22:03
  • 1
    \$\begingroup\$ I knew I recognized that output. I love that this idea is still going. \$\endgroup\$ – Carcigenicate Sep 5 '18 at 23:01
  • 2
    \$\begingroup\$ TFW you vaguely recognize a pattern in a question ಠ_ಠ then realize it's because you accidentally made it a year ago ಠ⌣ಠ. \$\endgroup\$ – Magic Octopus Urn Sep 6 '18 at 17:25
  • 1
    \$\begingroup\$ @MagicOctopusUrn Thanks for the inspiration. ;D \$\endgroup\$ – Kevin Cruijssen Sep 6 '18 at 17:26
  • 3
    \$\begingroup\$ @KevinCruijssen thanks for keeping the goofy quote haha! \$\endgroup\$ – Magic Octopus Urn Sep 6 '18 at 17:26

43 Answers 43

1
2
2
\$\begingroup\$

PHP, 148 146 143 141 Bytes

function s($s){for(;$i<strlen($s);++$i)f($i,$s);for(--$i;--$i>=0;)f($i,$s);}function f($i,$s){echo chunk_split($s,1,str_repeat(' ',$i))."
";}

You can test it like this:

<?php
error_reporting(0);

$s = 1234567890;
function s($s){for(;$i<strlen($s);++$i)f($i,$s);for(--$i;--$i>=0;)f($i,$s);}function f($i,$s){echo chunk_split($s,1,str_repeat(' ',$i))."
";}

Output

1234567890
1 2 3 4 5 6 7 8 9 0 
1  2  3  4  5  6  7  8  9  0  
1   2   3   4   5   6   7   8   9   0   
1    2    3    4    5    6    7    8    9    0    
1     2     3     4     5     6     7     8     9     0     
1      2      3      4      5      6      7      8      9      0      
1       2       3       4       5       6       7       8       9       0       
1        2        3        4        5        6        7        8        9        0        
1         2         3         4         5         6         7         8         9         0         
1        2        3        4        5        6        7        8        9        0        
1       2       3       4       5       6       7       8       9       0       
1      2      3      4      5      6      7      8      9      0      
1     2     3     4     5     6     7     8     9     0     
1    2    3    4    5    6    7    8    9    0    
1   2   3   4   5   6   7   8   9   0   
1  2  3  4  5  6  7  8  9  0  
1 2 3 4 5 6 7 8 9 0 
1234567890

Sandbox

Expanded version

 function s($s){
    //loop upwards 0-10
    for(;$i<strlen($s);++$i) f($i,$s);
     //decrement so it's odd, from 9 loop downwards to 0
    for(--$i;--$i>=0;)f($i,$s);
 }
 //2nd function to save space
 function f($i,$s){
     //chunk it, split 1 char, insert $i number of spaces
     echo chunk_split($s,1,str_repeat(' ',$i))."
";}

Attempt 2, 92 bytes

after seeing @Titus answer I reduced mine to this:

for(;++$i<2*$e=strlen($s=$argn);)echo chunk_split($s,1,str_repeat(' ',~-$e-abs($i-$e)))."
";

I was trying to think of a way to use 1 loop, instead of 2... Believe it or not, I almost never use the for loop in "real" code. It was the ~ bitwise Not, that I was missing...

It's sill a tiny bit longer at 92 so I don't feel so bad. But I will put it in as a second attempt anyway.

$argn is the input from the command line

Run as pipe with -nR or try it online.

Sandbox

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ It seems to me that your first version would be 4 bytes shorter if you used a named function f instead of assigning an anonymous one to $f - function f( saves 2 bytes over $f=function(, and you save another byte every time you call f(...) instead of $f(...). Alternatively, you could capture the $s, saving 2 bytes - ($i)use($s) is 4 bytes longer than ($i,$s), but you save 3 bytes for each call to $f($i) instead of $f($s,$i); in languages with automatic capture, like JS, this is more often a viable saving, because you don't pay the penalty of the use statement. \$\endgroup\$ – IMSoP Sep 7 '18 at 16:12
  • \$\begingroup\$ I do appreciate the help, I'm pretty new to code golf and don't really do it that much, one does get bored on the regular SO pages, though. I did think about using use but it feels longer, to do that sense $i is dynamic, it would have to be passed in by reference. So it has to be use(&$i) and the $i has to be defined before passing it by reference to $f. Which means setting it in the parent function, or before any other. For the function it could be function s($s,$i) and just know it has to be called with s($s,0) but it seems ugly, and that is around 11 bytes, use(&$i),$i \$\endgroup\$ – ArtisticPhoenix Sep 7 '18 at 17:14
  • \$\begingroup\$ We could use $s though and change the \n to a real line return. That gets it to 143 2 from the line ending and 1 from use \$\endgroup\$ – ArtisticPhoenix Sep 7 '18 at 17:31
  • \$\begingroup\$ Yes, I hadn't even considered putting $i into the use, because $s felt the "natural" capture, but it's always worth calculating the net saving. However, you can still save 2 bytes by just declaring a named function f instead of a closure: function s($s){for(;$i<strlen($s);++$i)f($i,$s);for(--$i;--$i>=0;)f($i,$s);}function f($i,$s){echo chunk_split($s,1,str_repeat(' ',$i))." ";} Extra functions like this are allowed according to this meta post: codegolf.meta.stackexchange.com/questions/7614/… \$\endgroup\$ – IMSoP Sep 8 '18 at 9:06
  • \$\begingroup\$ Updated, saved a couple \$\endgroup\$ – ArtisticPhoenix Sep 8 '18 at 11:27
1
\$\begingroup\$

Python 2, 67 bytes

s=input()
r=range(len(s))
for i in r+r[-2::-1]:print(' '*i).join(s)

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Red, 86 bytes

func[s][repeat n l: 2 *(length? s)- 1[foreach c s[prin pad c min n l - n + 1]print""]]

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Attache, 26 bytes

Bounce@{Join[_,Iota@_*sp]}

Try it online!

Explanation

Bounce@{Join[_,Iota@_*sp]}

       {                 }    anonymous lambda. input: _ (character array)
        Join[_,         ]     join each character by (vectorizes)
               Iota@_           the indices of _ (0 ... #_)
                     *sp        repeat a space by each index
Bounce@                       bounce the results (append reverse, but middle only once)
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Clean, 87 81 bytes

-2 thanks to Kevin Cruijssen

import StdEnv,Text
$s#l=length s
=[concat[rpad{c}(l-abs i)' '\\c<-s]\\i<-[~l..l]]

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Hi there. I'm afraid the output is slightly incorrect. Currently all lines also have leading spaces before the first character. The first character should all be in the same column, and the spaces should only be in between the characters (with optionally trailing spaces). \$\endgroup\$ – Kevin Cruijssen Sep 5 '18 at 9:27
  • \$\begingroup\$ @KevinCruijssen fixed. It was a typo lpad -> rpad \$\endgroup\$ – Οurous Sep 5 '18 at 20:29
  • \$\begingroup\$ Hi. I only now notice one more mistake a lot of other answers had too at first. Your middle line has length amount of spaces instead of length-1. For the 4-letter word 'test' for example, there should be 7 output lines instead of 9. You can fix that, and save 2 bytes at the same time, by removing the +1 it seems. :) \$\endgroup\$ – Kevin Cruijssen Sep 6 '18 at 7:06
  • 1
    \$\begingroup\$ @KevinCruijssen Fixed, and thanks! \$\endgroup\$ – Οurous Sep 6 '18 at 7:44
1
\$\begingroup\$

Brainbash, 142 bytes

-[-[-<]>>+<]>-<++++++++++>>*,+[~+~->,+]~[-*[.~>[-<<.>>>+<]>[<->+]<<~>]~>+<<<.>>]>--[->+<<+>]>[-<+>]<<+[-*[.~>[-<<.>>>+<]>[<->+]<<~>]~>-<<<.>>]

Try it online!

In one block:

-[-[-<]>>+<]>-<++++++++++>>*,+[~+~->,+]~[-*[.~>[-<<.>>>+<]>[<->+]<<~>]~
>+<<<.>>]>--[->+<<+>]>[-<+>]<<+[-*[.~>[-<<.>>>+<]>[<->+]<<~>]~>-<<<.>>]

Explanation

-[-[-<]>>+<]>-          constant for 32
<++++++++++             constant for 10
>>                      move to counter
*                       swap tapes while retaining pointer
,+[~+~->,+]             take input in tape while keeping track of how many characters
~                       move to counter on other tape
[                       repeat counter times:
    -                       update counter
    *                       swap tapes
    [                       for each character:
        .                       output it
        ~>[                     repeat secondary counter times:
            -                       update secondary counter
            <<.                     output a space
            >>>+<                   make a copy of the secondary counter
        ]
        >[<->+]                 restore secondary counter    
        <<~>                return to counter
    ]
    ~>+<<<.>>           update ternary counter and output a newline
]

>--                     fix offset

[->+<<+>]>[-<+>]<<+     various counter restoring

    [-*[.~>[-<
    <.>>>+<]>[
    <->+]<<~>]
    ~>-<<<.>>]          same as above but subtracting instead of adding
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

T-SQL, 215 214 bytes

DECLARE @v CHAR(32),@p VARCHAR(999),@ INT,@j INT,@k INT
SELECT @v=v,@=LEN(v),@j=-@+1FROM t
r:SET @p=''SET @k=1c:SET @p+=SUBSTRING(@v,@k,1)+SPACE(@+~ABS(@j))SET @k+=1
IF @k!>@ GOTO c
PRINT @p
SET @j+=1IF @j<@ GOTO r

Per our IO rules, input is taken from a pre-existing table t with varchar field v. Max size I've allowed is 32 characters, which tops out with the middle line being 32*31=992 characters long.

I've used a pure brute force nested-loop (using GOTO which is shorter than WHILE) with manual string construction, not very SQL-like at all. Still the best I could do (MS T-SQL has no native support for REGEX, except using CLR assemblies and manually importing System.Text.RegularExpressions).

EDIT: Here's the output for input "test":

test
t e s t 
t  e  s  t  
t   e   s   t   
t  e  s  t  
t e s t 
test

And here's a partial screenshot of the output for input "abcdefghijklmnopqrstuvwxyz":

Screenshot of output for 26-character input

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Hi there. Do you perhaps have a screenshot for one of the test cases (like 'test' for example) so I could verify everything is correct with the output? \$\endgroup\$ – Kevin Cruijssen Sep 7 '18 at 7:41
  • \$\begingroup\$ @KevinCruijssen Added two sample outputs. \$\endgroup\$ – BradC Sep 7 '18 at 13:45
  • \$\begingroup\$ Thanks, that seems to work great. +1 from me. :) \$\endgroup\$ – Kevin Cruijssen Sep 7 '18 at 13:51
  • 1
    \$\begingroup\$ Also, I barely know anything about T-SQL, but is it possible to golf @-ABS(@j)-1 to @+~ABS(@j)? I saw that T-SQL has a binary-not ~, but not sure if it works in the same way as Java/JavaScript/Python/etc. regarding this tip. \$\endgroup\$ – Kevin Cruijssen Sep 7 '18 at 13:54
  • 1
    \$\begingroup\$ @KevinCruijssen Actually, that does work! Down to 214 bytes! \$\endgroup\$ – BradC Sep 7 '18 at 14:32
1
\$\begingroup\$

C (gcc), 135 133 129 112 bytes

#define L{for(k=0;s[k];)printf("%c%*s",s[k++],i,"");puts("");}
i;k;f(char*s){for(i=0;s[i];i++)L for(--i;~--i;)L}

Try it online!

-2 bytes from Kevin Cruijssen

-4 bytes from ceilingcat

-17 bytes from ceilingcat

Ungolfed:

int i, k;
int f(char *s){
    for(i = 0; s[i] != '\x00'; i++) {
        for(k = 0; s[k] != '\x00'; k++) {
            printf("%c%*s", s[k], i, "");
            // print the character followed by the empty string padded with i spaces
        }
        putchar('\n');
    }
    for(i = i-2; i > -1; --i) {
        for(k = 0; s[k] != '\x00'; k++) {
            printf("%c%*s", s[k], i, "");
            // print the character followed by the empty string padded with i spaces
        }
        putchar('\n');
    }
}
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ You can golf 2 bytes by changing putchar(s[k]);for(j=0; to for(putchar(s[k]),j=0; so the brackets around the outer for-loop can be removed. \$\endgroup\$ – Kevin Cruijssen Sep 4 '18 at 16:56
  • \$\begingroup\$ 108 bytes \$\endgroup\$ – ceilingcat Dec 22 '18 at 0:38
1
\$\begingroup\$

JavaScript (Node.js), 102 100 98 96 bytes

f=(s,n=s.length,m=n+--n)=>[...Array(m)].map((_,i)=>[...s].join(` `.repeat(i<n?i:2*n-i))).join`

-2 by using [...]
-2 from @Kevin
-2 by tweak @Kevin

Try it online!

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Hi there! I'm afraid it's slightly incorrect. With input 'test' for example you are outputting 9 lines instead of 7. The middle longest line should have length-1 amount of spaces as delimiter, but currently your middle longest line has length amount of spaces as delimiter. \$\endgroup\$ – Kevin Cruijssen Sep 14 '18 at 10:55
  • \$\begingroup\$ changed from J to JS \$\endgroup\$ – user58120 Sep 20 '18 at 10:25
  • 1
    \$\begingroup\$ You can golf n-Math.abs(i-n) to i-n<0?i:2*n-i for -2 bytes. \$\endgroup\$ – Kevin Cruijssen Sep 20 '18 at 11:00
  • 2
    \$\begingroup\$ Welcome to PPCG! Here's a 74 byte version of your solution, taking input as an array of characters and outputting an array of lines: tio.run/##HcxBDsIgEADAux/… \$\endgroup\$ – Shaggy Sep 20 '18 at 12:30
  • 2
    \$\begingroup\$ It's allowed by the challenge spec: "I/O is flexible. Input may be taken as STDIN, argument, or function parameter. May be a list/array/stream of characters instead of string. Output may also be a list/array/stream of characters instead of strings; may be printed to STDOUT; returned as newline-delimited string; etc." \$\endgroup\$ – Shaggy Sep 20 '18 at 12:36
1
\$\begingroup\$

Pip -l, 14 9 bytes

aJsXPZ,#a

Takes the input string as a command-line argument. Try it online!

Note: the PZ operator is newer than this question.

Explanation

WIth example input abc:

           a is 1st cmdline arg; s is space (implicit)
      ,#a  Range(length(a))
           [0; 1; 2]
    PZ     Palindromize (append the reverse, but without doubling the center item)
           [0; 1; 2; 1; 0]
  sX       Repeat space that many times (vectorized)
           [""; " "; "  "; " "; ""]
aJ         Join a on those strings (vectorized)
           ["abc"; "a b c"; "a  b  c"; "a b c"; "abc"]
           Print (implicit)
           Each list element is printed on its own line, due to -l flag
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Rockstar, 135 133 bytes

listen to S
F takes X
cut S into L
join L with " "*X
say L

X's-1
while S at X+1
let X be+1
F taking X

while X
let X be-1
F taking X

Try it here (Code will need to be pasted in)

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

APL (Dyalog Extended), 28 bytes

{w←⍵⋄x←{,/⍵↑¨w}¨⍳≢⍵⋄⍪x,1↓⌽x}

Try it online!

Explanation

{w←⍵⋄x←{,/⍵↑¨w}¨⍳≢⍵⋄⍪x,1↓⌽x} For the next few steps: ⍵ → input.
 w←⍵                         Assign ⍵ to variable for next steps
    ⋄          ¨⍳≢⍵          loop through range 1 to length(⍵)
       {,/⍵↑¨w}              inner function: ⍵ → loop variable
                             w → input string
            ¨w               loop through each character in w
          ⍵↑                 take ⍵ characters from each char, appending ⍵-1 spaces
        ,/                   Catenate(join) the modified chars
     x←                      Assign the pattern to x
                         ⌽x  Take reverse of x
                       1↓    drop first element
                             (longest line should appear only once)
                     x,      Join with x
                    ⍪        Table it to display with newlines
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Lua: 132 characters

a=io.read()s=' 'l=function(o,n,z)for j=o,n,z do c=''for _,i in ipairs(a)do 
c=c..i..s:rep(j)end print(c)end end l(0,#a,1)l(#a-1,0,-1)

Long form:

a=io.read() -- using the input as a table, lua's version of arrays (and 
-- using it like an array anyway) Not 100% sure this is how the input goes
space=' ' -- need to declare this it seems so we can repeat it a number of times 
later
l = function(initialNumSpaces,maxNumSpaces,increment) 
for j=initialNumSpaces, maxNumSpaces, increment do 
  collector=''
  for _,i in ipairs(a)do  -- loop through the inputted string char by char
     collector=collector..i..space:rep(j) -- concat the char and spaces
  end 
  print(collector) -- print the collector
end 
end
l(0,#a,1) -- call the first half of the spaceship
l(#a-1,0,-1) -- call the second half of the spaceship
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Hi there, welcome to PPCG! Would it be possible add a TryItOnline-link with test code for your Lua program/function? (PS: You can add a trailing # in front of your "Lua: 132 characters" to make it a title like most of the other answers. :) \$\endgroup\$ – Kevin Cruijssen Sep 14 '18 at 8:06
1
2

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.