g | x | w | all
Bytes Lang Time Link
078AWK250728T182043Zxrs
107Swift 6250725T210607ZmacOSist
136Tcl250707T104354Zsergiol
077Zsh201212T100356Zroblogic
005Vyxal j210818T034455Zemanresu
006Thunno 2 N230722T044654ZThe Thon
082Bash180907T132418Zagc
020APL Dyalog Extended200912T045956ZRazetime
008Japt180904T135906ZLuis fel
133Rockstar200911T112004ZShaggy
009Pip l180908T192049ZDLosc
141PHP180906T230653ZArtistic
096JavaScript Node.js180914T102429Zuser5812
006Japt180904T141233ZShaggy
024K oK180904T205748Zmkst
132Lua180914T050041ZDolgubon
nan180904T163910Zpizzapan
111C gcc180904T224823ZConor O&
043Perl 6180909T042637ZJo King
013MATL180905T180306ZGiuseppe
059Haskell180907T185502Zბიმო
059Haskell180906T210542Znimi
214TSQL180906T223012ZBradC
034Perl 5 + M5.010 nlF180907T073816ZDom Hast
00905AB1E legacy180904T210805ZKevin Cr
0538086 machine code180905T164935Zuser5434
142Brainbash180906T182412ZConor O&
115Oracle SQL180906T125823ZMT0
081Clean180904T215609ZΟurous
082Scala180905T155756ZAndrew K
098C#180905T113223ZRobIII
054PowerShell180904T154505ZAdmBorkB
115Java JDK 10180904T143810ZOlivier
010Stax180905T115027Zwastl
079R180904T164737ZJ.Doe
00905AB1E180904T140405ZEmigna
026Attache180904T222701ZConor O&
012Pyth180904T205308ZMr. Xcod
023K4180904T205126Zmkst
089PHP180904T185620ZTitus
086Red180904T192316ZGalen Iv
049Ruby180904T142656ZKirill L
009Jelly180904T162047ZErik the
135Pascal FPC180904T153720ZAlexRace
065Python 2180904T140648ZRod
008Canvas180904T142710Zdzaima
067Python 2180904T144526ZTFeld
010Charcoal180904T142706ZNeil
053JavaScript ES6180904T141313ZArnauld

AWK, 78 bytes

{for(;i++<g=NF*2;s=s" "){for(j=0;j++<g;)t[i]=t[i]$j s;print i<NF?t[i]:t[g-i]}}

Attempt This Online!

{for(;i++<g=NF*2;  # twice length of input
s=s" ")            # padding
{for(j=0;j++<g;)   # craft strings
t[i]=t[i]$j s;     # concat letters and padding
print i<NF?        # if less than input length
t[i]               # print current string
:t[g-i]}}          # else reverse

Swift 6, 109 107 bytes

{s in{c in(-c...c).map{n in print(s.map{"\($0)"+{String.init}()(" ",c-abs(n))}.joined())}}((s+"").count-1)}

Try it on SwiftFiddle!

Tcl, 136 bytes

proc P s {set n -[set m [expr [string le $s]-1]]
time {puts [join [split $s ""] [format %[expr $m-abs([incr n]-1)]s ""]]} [expr 2*$m+1]}

Try it online!

Zsh, 95 77 bytes

Try it online!   95 bytes

j=$[$#1-1];for i ({-$j..$j})echo&&for x (${(s::)1})printf %-$[$#1-${i#-}]s $x

Takes input from argument $1. Set j to length-1. Iterate i from -j to j. For each character x in the input string, print x and append a number of spaces equal to length minus the absolute value of i

Vyxal j, 5 bytes

ż∞v↲∩

Try it Online! -5 bytes thanks to lyxal.

ż     # range from 1 to length of input
 ∞    # Palindromised
  v↲  # For each character of the input, pad left by each of the above
    ∩ # Transpose
      # (j flag formats list of lines as a string)

Thunno 2 N, 6 bytes

Żıṣj;Ɱ

Try it online!

Explanation

Żıṣj;Ɱ  # Implicit input
Ż       # Push [0..len(input))
 ı  ;   # Map over this list:
  ṣ     #  Push that many spaces
   j    #  Join input by this string
     Ɱ  # Then, palindromise
        # Join on newlines
        # Implicit output

Bash, 115, 109, 105, 100, 97, 96, 92, 91, 90, 82 bytes

-5 & -3 thanks to Kevin Cruissen -8 thanks to roblogic

for((c=f=1;f;c-=2*(f>=${#1}),f+=c))
{ printf '%-'${f}'.c' `grep -o .<<<"$1"`
echo
}

Try it online!

--- Note that since the \ is a shell escape char, the test case )}/\ should be entered with an extra \ like this: )}/\\.

APL (Dyalog Extended), 28 20 bytes

{↑x,1↓⌽x←∊¨↑¨∘⍵¨⍳≢⍵}

Try it online!

-8 bytes from Adám.

Explanation

{↑x,1↓⌽x←∊¨↑¨∘⍵¨⍳≢⍵} ⍵ → input.
                ⍳≢⍵  range 1..length(input)
           ↑¨∘⍵¨     pad each input character with i spaces
         ∊¨          flatten each row
       x←            save that as x
  x,1↓⌽              join it with its reverse
 ↑                   convert to matrix(join with newlines)

Japt, 9 8 bytes

-1 byte from @Shaggy

ÊÆ¬qXîÃê

ÊÆ¬qXîÃê        Full program, implicity input U
ÊÆ              Range from 0 to U length and map
  ¬             split U at ""
   qXîà         join U using " " times range current value
        ê       horizontal mirror

Try it online!

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)

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

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

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!

Japt, 8 6 bytes

Takes input as an array of characters, outputs an array of strings.

£qYçÃê

Try it


Explanation

£          :Map each element at (0-based) index Y
 q         :  Join input with
  Yç       :   Space repeated Y times
    Ã      :End Map
     ê     :Palindromise

Original, 8 bytes

I/O is a string. Uses the -R flag. Includes trailing spaces on each line.

¬£múYÄÃê

Try it

Explanation

             :Implicit input of string U
¬            :Split
 £           :Map each character at 0-based index Y
  m          :  Map original U
   ú         :    Right pad with spaces to length ...
    YÄ       :     Y+1
      Ã      :End map
       ê     :Palindromise
             :Implicitly join with newlines

K (oK), 25 24 bytes

Solution:

,/'(1+a,1_|a:!#x)$\:+,x:

Try it online!

Explanation:

Port of my K4 solution:

,/'(1+a,1_|a:!#x)$\:+,x: / the solution
                      x: / save input as x
                     ,   / enlist
                    +    / flip
                 $\:     / pad ($) right by each-left (\:)
   (            )        / do this together
              #x         / count length of input,           e.g. 3
             !           / range 0..length,                 e.g. 0 1 2
           a:            / save as a
          |              / reverse it,                      e.g. 2 1 0
        1_               / drop first,                      e.g. 1 0
      a,                 / join to a,                       e.g. 0 1 2 1 0
    1+                   / add 1,                           e.g. 1 2 3 2 1
,/'                      / flatten (,/) each (')

Notes:

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

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');
    }
}

C (gcc), 131 129 111 bytes

i;x;f(k,j)char*k,*j;{x=strlen(k)-1;for(i=0;i<x-~x;i+=puts(""))for(j=k;*j;)printf("%c%*s",*j++,i<x?i:2*x-i,"");}

Try it online!

-20 bytes thanks to ceilingcat!

#import<string.h>
i;x;f(k,j)char*k,*j;{x=strlen(k)-1;for(i=0;i<x-~x;i+=puts(""))for(j=k;*j;)printf("%c%*s",*j++,i<x?i:2*x-i,"");}

Try it online!

Or, if length can be accepted as a parameter:

C (gcc), 105 102 bytes

-1 byte thanks to ceilingcat!

i;x;f(k,x,j)char*k,*j;{for(i=!x--;i<x-~x;i+=puts(""))for(j=k;*j;)printf("%c%*s",*j++,i<x?i:2*x-i,"");}

Try it online!

Perl 6, 43 bytes

{(0....comb-1...0)>>.&{join ' 'x$^a,.comb}}

Try it online!

Returns a list of lines.

Explanation:

 {                                         }  # Anonymous code block
  (0....comb-1...0) # A list from
   0                  # 0
    ...               # to
       .comb-1        # the length of the input string -1
              ...     # back to
                 0    # 0
                   >>.&{                  }  # Map each number to
                        join        ,.comb   # Join the list of characters
                             ' 'x$^a         # With the number of spaces

MATL, 25 22 13 bytes

zZv"Gtz@he!1e

Try it online!

Thanks to Luis Mendo for suggesting a 5 byte golf, which then inspired me to shave off 4 more bytes!

Explanation, with example input 'abc':

         # Implicit input, 'abc'
z        # find number of nonzero elements (length of string)
         # stack: [3]
Zv       # symmetric range
         # stack: [[1 2 3 2 1]]
"        # begin for loop, iterating over [1 2 3 2 1] as the loop indices
G        # push input
         # stack: ['abc']
tz       # dup and push length
         # stack: ['abc', 3]
@        # push loop index, i (for example, 2)
         # stack: ['abc', 3, 2]
h        # horizontally concatenate
         # stack: ['abc', [3, 2]]
e!       # reshape to matrix of 3 rows and i columns, padding with spaces, and transpose
         # stack: [['abc';'   ';'   ']]
1e       # reshape to matrix of 1 row, leaving last value on stack
         # stack: ['a  b  c  ']
         # implicit end of for loop
         # implicit end of program, display stack contents

Haskell, 60 59 bytes

(init<>reverse).(scanl(?)<*>tail)
a?_=do u<-a;u:[' '|' '<u]

Try it online!

Explanation

For a string (eg. "abc") we apply first

scanl (?) <*> tail

which is the same as

\str -> scanl (?) str (tail str)

This repeatedly applies (?) (appends a space to each character in the range [33..]) to the str until there are that many strings as str has characters: ["abc","a b c ", "a b c "]

Now we only need to concatenate the result (minus the last element) with its reversed counter part:

init<>reverse

Haskell, 64 60 59 bytes

(""#)
a#s|l<-(:a)=<<s,w<-' ':a=l:[x|w<(' '<$s),x<-w#s++[l]]

Try it online!

a#s                         -- take a string of spaces 'a' and the input string 's'
 |l<-(:a)=<<s               -- let 'l' be the current line, i.e. the spaces in 'a'
                            -- appended to each char in 's'
  w<-' ':a                  -- let 'w' be 'a' with an additional space   
 =l                         -- return that 'l'
   :[   |w<(' '<$s)   ]     -- and, if 'w' is shorter than 's',
     x  ,x<-w#s++[l]        -- followed by a recursive call with 'w' 
                            -- and by another copy of 'l'

(""#)                       -- start with an empty 'a'

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

Perl 5 + -M5.010 -nlF, 34 bytes

$,=$"x($#F-abs),say@F for-$#F..$#F

Try it online!

05AB1E (legacy), 9 bytes

εINúíJ}û»

Input as list of characters.

Try it online or verify all test cases.

Explanation:

ε     }    # Map each character in the input to:
 I         #  Take the input
  Nú       #  Prepend each with the 0-indexed amount of spaces
           #   i.e. ["t","e","s","t"] & 3 → ["   t","   e","   s","   t"]
    í      #  Reverse each item
           #   i.e. ["   t","   e","   s","   t"] → ["t   ","e   ","s   ","t   "]
     J     #  Join them together to a single string
           #   i.e. ["t   ","e   ","s   ","t   "] → "t   e   s   t   "
       û»  # Palindromize the list, and join by newlines
           #  i.e. ["test","t e s t ","t  e  s  t  ","t   e   s   t   "]
           #   → "test\nt e s t \nt  e  s  t  \nt   e   s   t   \nt  e  s  t  \nt e s t \ntest"

8086 machine code, 56 53 bytes

00000000  bf 35 01 57 ba 01 00 52  be 82 00 b3 ff ac 59 51  |.5.W...R......YQ|
00000010  aa 3c 0d 74 07 b0 20 e2  f7 43 eb f1 b0 0a aa 59  |.<.t.. ..C.....Y|
00000020  00 d1 e3 08 38 cb d6 08  c2 51 eb dc c6 05 24 5a  |....8....Q....$Z|
00000030  b4 09 cd 21 c3                                    |...!.|
00000035

Assembled from:

org 0x100
use16
        mov di, buffer
        push di
        mov dx, 1
        push dx
nextl:  mov si, 0x82
        mov bl, -1
nextc:  lodsb
        pop cx
        push cx
stor:   stosb
        cmp al, 0x0d
        je cr
        mov al, ' '
        loop stor
        inc bx
        jmp nextc
cr:     mov al, 0x0a
        stosb
        pop cx
        add cl, dl
        jcxz done
        cmp bl, cl
        salc
        or dl, al
        push cx
        jmp nextl
done:   mov [di], byte '$'
        pop dx
        mov ah, 0x09
        int 0x21
        ret
buffer:

Test case:

screenshot

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

Oracle SQL, 115 bytes

Not a golfing language but...

SELECT TRIM(REGEXP_REPLACE(v,'(.)',LPAD('\1',1+LENGTH(v)-ABS(LEVEL-LENGTH(v)))))FROM t CONNECT BY LEVEL<2*LENGTH(v)

Assuming that the value is in column v of table t:

SQL Fiddle

Oracle 11g R2 Schema Setup:

CREATE TABLE t ( v ) AS
  SELECT 'test' FROM DUAL;

Query 1:

SELECT TRIM(REGEXP_REPLACE(v,'(.)',LPAD('\1',1+LENGTH(v)-ABS(LEVEL-LENGTH(v)))))
FROM   t
CONNECT BY LEVEL<2*LENGTH(v)

Results:

(SQLFiddle prints the values right-aligned in the column for some reason... there are no leading spaces)

| TRIM(REGEXP_REPLACE(V,'(.)',LPAD('\1',1+LENGTH(V)-ABS(LEVEL-LENGTH(V))))) |
|---------------------------------------------------------------------------|
|                                                                      test |
|                                                                   t e s t |
|                                                                t  e  s  t |
|                                                             t   e   s   t |
|                                                                t  e  s  t |
|                                                                   t e s t |
|                                                                      test |

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!

Scala, 82 bytes

for(i<-(0 to a.size)union(-a.size to 0))println(a.map(_+" "*Math.abs(i)).mkString)

Try it online

Scala has lot of shortcuts that are helping me here and that is quite readable! Try Scala

C#, 113 105 98 bytes

s=>{for(int l=s.Length,i=-l;++i<l;)WriteLine(Join("",s.Select(c=>$"{c}".PadRight(i<0?l+i:l-i))));}

Try it online!

PowerShell, 66 54 bytes

-12 bytes thanks to mazzy

0..($x=($a=$args).count-1)+$x..0|gu|%{$a-join(' '*$_)}

Try it online!

Takes input via splatting, which on TIO manifests as separate command-line arguments for each character.

We first set $a=$args as the input argument. Then we set $x equal to the .count of that array -1. We then need to loop through the letters to construct the spaceship. That's done by constructing a range from 0 to $x, then $x back down to 0, then using Get-Unique to pull out just the appropriate range.

Each iteration, we take our input arguments and -join them together with the corresponding number of spaces. Each of those strings is left on the pipeline, and an implicit Write-Output gives us newlines for free when the program completes.

Java (JDK 10), 115 bytes

s->{for(int l=s.length(),i=-l;++i<l;)System.out.printf(s.replaceAll(".","%-"+(i<0?l+i:l-i)+"s")+"%n",s.split(""));}

Try it online!

Stax, 10 bytes

Ç·9ƒù▌╘Ä┘e

Run and debug it

Outputs with trailing whitespace on each line.

Explanation:

%R|pmx{]n(m Full program, unpacked, implicit input
%           Length of input
 R          1-based range
  |p        Palindromize
    m       Map:
     x{   m   Map over characters of input:
       ]        Character -> string
        n(      Right-pad to length given by outer map value
              Implicit flatten and output

R, 105 99 85 84 79 bytes

-6 thanks to @Kevin Cruissen and @Giuseppe

-14 from changing to a regex based method

-1 thanks to @Giuseppe

-5 thanks to @digEmALl

function(w,n=nchar(w)-1)write(trimws(Map(gsub,"",strrep(" ",n-abs(n:-n)),w)),1)

Try it online!

05AB1E, 10 9 bytes

Saved 1 bytes thanks to Adnan

εINð×ý}û»

Try it online!

Explanation

ε            # apply to each in input
 I           # push the input
  Nð×        # push <index> spaces
     ý       # merge the input on the spaces
      }      # end loop
       û     # palendromize
        »    # join on newlines

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)

Pyth, 12 bytes

Just my mandatory Pyth submission. I am quite proud of this so an explanation will likely come soon.

+P_=jRQ*L;_U

Try it here!

+P_=jRQ_.e*d

Try it here!

K4, 23 bytes

Solution:

,/'(1+a,1_|a:!#x)$\:$x:

Example:

q)k),/'(1+a,1_|a:!#x)$\:$x:"Spaceship"
"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"

Explanation:

Has trailing whitespace on each line.

,/'(1+a,1_|a:!#x)$\:$x: / the solution
                     x: / save input as x,                 e.g. "abc"
                    $   / string,                          e.g. (,"a";,"b";,"c")
                 $\:    / pad ($) right by each-left (\:)
   (            )       / do this together
              #x        / count length of input,           e.g. 3
             !          / range 0..length,                 e.g. 0 1 2
           a:           / save as a
          |             / reverse it,                      e.g. 2 1 0
        1_              / drop first,                      e.g. 1 0
      a,                / join to a,                       e.g. 0 1 2 1 0
    1+                  / add 1,                           e.g. 1 2 3 2 1
,/'                     / flatten each

PHP, 88 89 bytes

for(;++$i<2*$e=count($a=str_split($argn));)echo join(str_pad("",~-$e-abs($i-$e)),$a),"\n";

requires PHP 5 or later for str_split. Run as pipe with -nR or try it online.

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!

Ruby, 54 49 bytes

->a{(-(z=a.size-1)..z).map{|i|a*(?\s*(z-i.abs))}}

Try it online!

Takes input as an array of characters, outputs array of strings.

Jelly, 9 bytes

jⱮLḶ⁶ẋƲŒḄ

Try it online!

Returns a list of lines; output prettified over TIO.

Pascal (FPC), 143 135 bytes

var s:string;i,j,l:word;begin read(s);l:=length(s);repeat i:=i+1;for j:=1to l do write(s[j],'':l-abs(l-i)-1);writeln until i=l*2-1 end.

Try it online!

I will probably win only against Lenguage...

Python 2, 72 70 68 66 65 bytes

-2 bytes thanks to Kevin Cruijssen
-3 bytes thanks to ovs

w=input();c=s=-1
while c:print(' '*~c).join(w);s*=w[:c]>'';c+=s|1

Try it online!

Canvas, 8 bytes

┐² ×*]──

Try it here!

The 7 byte version was too good for this challenge..

Python 2, 67 bytes

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

Try it online!

Charcoal, 10 bytes

Eθ⪫θ× κ‖O↓

Try it online! Link is to verbose version of code. Explanation:

Eθ          Map over characters of input string
  ⪫θ        Join characters of input string using
    ×       a literal space repeated 
      κ     current index number of times
            Implicitly print each result on its own line
       ‖O↓  Reflect vertically with overlap

JavaScript (ES6), 53 bytes

Takes input as an array of characters.

f=(s,p=i='',o=s.join(p)+`
`)=>s[++i]?o+f(s,p+' ')+o:o

Try it online!