Output a Pyramid (or Highway)

Given a non-empty string s, with even length, and a positive integer n, representing its height, compose a pyramid using the following rules:

The pyramid should contain n non-empty lines; trailing newlines are allowed. For each 1 <= i <= n, the i-th line should contain the string with each individual character repeated in-place i times; abcd repeated 3 times as such becomes aaabbbcccddd. Each line should be centered with padding spaces so that the middle of each line is vertically aligned. Trailing spaces at the end of each line are permitted. You can also have up to one leading newline but no other whitespace before the first line.

The input string is not guaranteed to be a palindrome.

Test Case

s = 'o-o  o-o', n = 10:

o-o  o-o
oo--oo    oo--oo
ooo---ooo      ooo---ooo
oooo----oooo        oooo----oooo
ooooo-----ooooo          ooooo-----ooooo
oooooo------oooooo            oooooo------oooooo
ooooooo-------ooooooo              ooooooo-------ooooooo
oooooooo--------oooooooo                oooooooo--------oooooooo
ooooooooo---------ooooooooo                  ooooooooo---------ooooooooo
oooooooooo----------oooooooooo                    oooooooooo----------oooooooooo

• Sandbox Post created by user42649, which was my account until it got deleted. – HyperNeutrino Jun 21 '17 at 0:19
• Can the output for a function on this question be a list of strings, each representing a line, or should it be joined by newlines? – notjagan Jun 21 '17 at 0:46
• Output a pyramid You surely mean a highway! – Luis Mendo Jun 21 '17 at 8:32
• Looks like an Aztec pyramid! – QBrute Jun 21 '17 at 9:09
• @QBrute Na. Was made by a Goa'uld :) – theblitz Jun 21 '17 at 9:41

05AB1E, 9 bytes

γ².D)ƶJ.C


Try it online!

γ was, in no short amount, inspired by Adnan's answer; but S would also work.

γ          # Split into runs.    | ['0','-','0']
².D)      # Push n times.       | [['0','-','0'],['0','-','0'],['0','-','0']]
ƶ     # Lift by index.      | [['0','-','0'],['00','---','00'],['000','---','000']]
J    # Inner join.         | ['0-0','00--00','000---000']
.C  # Center.             | Expected output.

• I can't believe someone actually downvoted your mistaken post :/ – Jonathan Allan Jun 21 '17 at 18:06
• @JonathanAllan the frequency of my avoidable mistakes deserves negativity to some degree. – Magic Octopus Urn Jun 21 '17 at 18:08

05AB1E, 11 bytes

F²γN>×J}».C


Uses the 05AB1E encoding. Try it online!

• It starts going funky with inputs above 168. otherwise great! – tuskiomi Jun 21 '17 at 16:56
• @carusocomputing » joins the inner arrays by spaces. Replacing it by J should work (and I think you should post that as a different answer). – Adnan Jun 21 '17 at 17:58
• Ah! Has it always been that way? If so, cool, if not I must've missed that. Thanks, will do. – Magic Octopus Urn Jun 21 '17 at 18:01

Jelly, 14 13 bytes

LH×Ḷ}Ṛ⁶ẋżxÐ€Y


Try it online!

How it works

LH×Ḷ}Ṛ⁶ẋżxÐ€Y  Main link. Arguments: s (string), n (integer)

L              Get the length l of s.
H             Halve it, yielding l/2.
Ḷ}          Unlength right; yield [0, ... n-1].
×            Compute [0, l/2, ..., l(n-1)/2].
Ṛ         Reverse; yield [l(n-1)/2, ..., l/2, 0].
⁶ẋ       Space repeat; create string of that many spaces.
xÐ€   Repeat in-place each; repeat the individual characters of s
1, ..., n times, yielding an array of n strings.
ż      Zipwith; pair the k-th string of spaces with the k-th string of
repeated characters of s.
Y  Sepatate the resulting pairs by linefeeds.


C# (.NET Core), 139 137 136 130 bytes

using System.Linq;s=>n=>Enumerable.Range(0,n).Select(i=>"".PadLeft((n+~i)*s.Length/2)+string.Concat(s.Select(c=>new string(c,i))))


Try it online!

Returns an enumeration of strings with the lines of the drawing. Once joined the result is like this:

                        ಠ_ಠ  ಠ_ಠ
ಠಠ__ಠಠ    ಠಠ__ಠಠ
ಠಠಠ___ಠಠಠ      ಠಠಠ___ಠಠಠ
ಠಠಠಠ____ಠಠಠಠ        ಠಠಠಠ____ಠಠಠಠ
ಠಠಠಠಠ_____ಠಠಠಠಠ          ಠಠಠಠಠ_____ಠಠಠಠಠ
ಠಠಠಠಠಠ______ಠಠಠಠಠಠ            ಠಠಠಠಠಠ______ಠಠಠಠಠಠ
ಠಠಠಠಠಠಠ_______ಠಠಠಠಠಠಠ              ಠಠಠಠಠಠಠ_______ಠಠಠಠಠಠಠ

• 2 bytes saved thanks to Kevin Cruijssen!
• 1 byte saved thanks to Value Ink!
• 6 bytes saved thanks to LiefdeWen!
• You can save two bytes by removing the parenthesis at (n-i-1)*s.Length/2. And I like your test cases. +1 :) – Kevin Cruijssen Jun 21 '17 at 8:04
• ಠ_ಠ intensifies – Magic Octopus Urn Jun 21 '17 at 19:25
• Obligatory "~i is equivalent to -i-1", so you can save a byte by changing (n-i-1) to (n+~i). – Value Ink Jun 22 '17 at 9:37
• and you can use currying so s=>n=>... for another byte – LiefdeWen Jun 22 '17 at 11:18
• @CarlosAlejo Sorry for posting seperate edits but you can also replace new string(' '... with "".PadLeft(... – LiefdeWen Jun 22 '17 at 11:34

Cheddar, 71 64 bytes

Saved 7 bytes thanks to @ValueInk

(s,n)->(1|>n=>i->(s.len*(n-i)/2)*" "+s.sub(/./g,"$&"*i)).asLines  Try it online! I will add explanation in a bit Explanation (string, count)->( 1 |> count // 1..count, the amount of rep/char per line => i -> ( // Map over the range s.len*(n-i)/2 // Calculate amount of spaces and repeat by it. )*" " + s.sub(/./g,"$&"*i) // replace each character, duplicate the amount of times *i
).asLines              // return the above joined with newlines

• No problem! I wonder if Cheddar has a center function that you can use like I have on my Ruby answer, because that could potentially save bytes as well. – Value Ink Jun 21 '17 at 2:17

Ruby, 58 bytes

->s,n{(1..n).map{|i|s.gsub(/./){$&*i}.center s.size*n}*$/}


Try it online!

Java 8, 188186185183181 173 bytes

s->n->{String r="";int l=s.length()/2,x=l*n,i,j;for(i=0;i++<n;r+="\n"){r+=s.format("%"+x+"s",r).substring(0,x-i*l);for(char c:s.toCharArray())for(j=0;j++<i;r+=c);}return r;}


-2 bytes (185 → 183) due to a bug-fix (it was outputting n+1 lines instead of n). Doesn't happen often that a bug-fix saves bytes. :)
-2 bytes (183 → 181) thanks to @OlivierGrégoire

Explanation:

Try it here.

s->n->{                          // Method with String and integer parameter and String return-type
String r="";                   //  Return-String
int l=s.length()/2,            //  Halve the length of the input-String
x=l*n,                     //  Halve the length * the input integer
i,j;                       //  Some temp integers
for(i=0;i++<n;                 //  Loop (1) n times
r+="\n"){                  //    And after every iteration, add a new-line
r+=s.format("%"+x+"s",r).substring(0,x-i*l);
//   Add the appropriate trailing spaces
for(char c:s.toCharArray())  //   Loop (2) over the characters of the String
for(j=0;j++<i;r+=c);       //    And repeat each one more than in the previous row
//   End of loop (2) (implicit / single-line body)
}                              //  End of loop (1)
return r;                      //  Return the result-String
}                                // End of method

• If you move your ints first, you can declare r="",q=s.format("%"+x+"s",r) to save 2 bytes. Lots of move for just two bytes :( – Olivier Grégoire Jun 22 '17 at 9:24
• @OlivierGrégoire Thanks! By using s.format("%"+x+"s",r) directly I've been able to save 8 more bytes after your golf. :) – Kevin Cruijssen Jun 22 '17 at 12:04

JavaScript (ES6), 85 bytes

Takes input in currying syntax (string)(height). Includes a leading newline.

s=>g=(n,p=
)=>n?g(n-1,p+' '.repeat(s.length/2))+p+s.replace(/./g,c=>c.repeat(n)):''


Demo

let f =

s=>g=(n,p=
)=>n?g(n-1,p+' '.repeat(s.length/2))+p+s.replace(/./g,c=>c.repeat(n)):''

o.innerHTML = f('o-o  o-o')(10)
<pre id=o></pre>

• There are leading whitespaces before the last line, is that allowed? – Charlie Jun 21 '17 at 8:15
• @CarlosAlejo Oh, that was an unintended side-effect of a last-minute update. Now fixed. Thanks for reporting this! – Arnauld Jun 21 '17 at 8:20

Charcoal, 19 bytes

Ｆ⁺¹Ｎ«Ｊ±×ι÷Ｌη²ιＦηＦικ


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

Ｆ⁺¹Ｎ«       for (Plus(1, InputNumber())) {


We need lines repeated 1..n times. The easiest way to achieve this is to loop from 0 to n, as loop 0 is basically a no-op.

Ｊ±×ι÷Ｌη²ι       JumpTo(Negate(Times(i, IntDivide(Length(h), 2))), i);


Position the cursor so that the resulting line is centred.

ＦηＦικ           for (h) for (i) Print(k);


And this is how simple printing each character repeated i times is.

Python 2, 75 77 bytes

s,n=input()
for i in range(n):print''.join(c*-~i for c in s).center(len(s)*n)


Try it online!

• Dang, I had nearly the same answer, but I was unsure whether a function could return a list of lines. If so, I'll post mine as a separate answer, but if not it would be too similar to post. – notjagan Jun 21 '17 at 0:56
• Wow, there's a center builtin? I really need to read the docs sometimes :P – HyperNeutrino Jun 21 '17 at 0:59
• Returns the wrong output; this has a leading blank line followed by n-1 rows. – Value Ink Jun 21 '17 at 2:20
• You have also some leading whitespaces before the last line, is that allowed? – Charlie Jun 21 '17 at 8:18
• @FryAmTheEggman that might be true, but it's still returning 9 lines of pyramid when the input is 10... – Value Ink Jun 21 '17 at 8:30

SOGL V0.12, 14 bytes

ā.∫dI*Hd⁄»±IFž


Try it Here!

• +1 for using ∫dI. – Zacharý Jun 21 '17 at 17:12

Javascript, 105 bytes

(s,n)=>Array(N=n).fill().reduce(a=>a+'\n'+' '.repeat(--n*s.length/2)+s.replace(/./g,_=>_.repeat(N-n)),'')


After a few years off, the Stretch Maniac is back, hopefully slightly more educated this time.

• You have too many leading spaces on each line. – Shaggy Jun 21 '17 at 8:25
• Here's a 99 byte ES8 version of this method I came up with before I saw yours: s=>n=>[...Array(x=n)].reduce(a=>a+'\n'.padEnd(--x*s.length/2+1)+s.replace(/./g,c=>c.repeat(n-x)),'') - you'll need to replace the 's with backticks and the \n with a literal newline. – Shaggy Jun 21 '17 at 13:39

• Saved 4 bytes thanks to nimi
s#n=unlines[(' '<$[1,3..(n-m)*length s])++((<$[1..m])=<<s)|m<-[1..n]]


Try it online!

• If you use a step in .., you can drop the div: (' '<$[1,3..(n-m)*length s]). – nimi Jun 21 '17 at 15:10 • Another 5 bytes off. – ბიმო Dec 29 '17 at 23:56 APL (Dyalog), 33 31 bytes 2 bytes golfed thanks to @ZacharyT by removing unnecessary parentheses {↑((' '/⍨(.5×≢⍵)×⍺-⊢),⍵/⍨⊢)¨⍳⍺}  Try it online! Explanation The right argument ⍵ is the string and the left argument ⍺ is the number. {↑((' '/⍨(.5×≢⍵)×⍺-⊢),⍵/⍨⊢)¨⍳⍺} ⍳⍺ Range 1 .. ⍺ ( )¨ For each element (let's call it i) do: ⍵/⍨⊢ Replicate ⍵ i times ( ), Concatenated with (.5×≢⍵)×⍺-⊢ (⍺-i)×(len(⍵)×0.5) ' '/⍨ spaces ↑ Convert the resulting array to a 2D matrix  • Do you need the parens around ⍺-⊢? – Zacharý Jun 21 '17 at 17:07 • @ZacharyT You're right, I don't need them. Thanks :) – Kritixi Lithos Jun 22 '17 at 7:19 SWI Prolog, 398 bytes It is not the most compact solution (maybe somewhere reinventing the wheel instead of using built-in procedures), but it appers to work. w(0). w(X):-write(' '),Y is X-1,w(Y). s(S,N):-string_length(S,X),Y is div(X,2)*N,w(Y). d(S,N,R):-atom_chars(S,A),e([],A,N,R). e(B,[H|T],N,R):-l(B,H,N,I),e(I,T,N,R). e(B,[],_,B). a([], L, L). a([H|T],L,[H|R]):-a(T,L,R). l(L,_,0,L). l(L,I,N,R):-M is N-1,l(L,I,M,T),a(T,[I],R). o([]):-nl. o([H|T]):-write(H),o(T). p(S,N):-p(S,N,N). p(_,0,_). p(S,N,L):-Q is N-1,p(S,Q,L),d(S,N,R),W is L-N,s(S,W),o(R).  Test: ?- p("o-o o-o",10). o-o o-o oo--oo oo--oo ooo---ooo ooo---ooo oooo----oooo oooo----oooo ooooo-----ooooo ooooo-----ooooo oooooo------oooooo oooooo------oooooo ooooooo-------ooooooo ooooooo-------ooooooo oooooooo--------oooooooo oooooooo--------oooooooo ooooooooo---------ooooooooo ooooooooo---------ooooooooo oooooooooo----------oooooooooo oooooooooo----------oooooooooo true .  Explanation: w and s writes proper amount of leading spaces: w(0). w(X):-write(' '),Y is X-1,w(Y). s(S,N):-string_length(S,X),Y is div(X,2)*N,w(Y).  d manages the "duplication" of characters and e is it's recursive facility: //d(String, Number of repetitions, Result) d(S,N,R):-atom_chars(S,A),e([],A,N,R). e(B,[H|T],N,R):-l(B,H,N,I),e(I,T,N,R). e(B,[],_,B).  a and l append to the result (maybe there exists a built in procedure?): a([], L, L). a([H|T],L,[H|R]):-a(T,L,R). l(L,_,0,L). l(L,I,N,R):-M is N-1,l(L,I,M,T),a(T,[I],R).  o creates the output: o([]):-nl. o([H|T]):-write(H),o(T).  and finally the p is the main method: p(S,N):-p(S,N,N). p(_,0,_). //p(String, Current level, Number of levels) :- go to the bottom, create pyramide level, write whitespaces, write the level p(S,N,L):-Q is N-1,p(S,Q,L),d(S,N,R),W is L-N,s(S,W),o(R).  Japt, 20+1=2119+1=20 14 bytes Outputs an array of lines - add 2 bytes if that's not permitted. Võ@®pXÃù°V*UÊz  Test it Explanation  :Implicit input of string U & integer V Võ :Generate an array of integers from 1 to V, inclusive @ :Map over the elements of the array ® :Map over the characters of U p :Repeat the current character ... X : X (the current element) times. Ã :End string mapping. ù :Left pad each line with spaces to length... °V : V incremented by one... * : multiplied by... UÊ : the length of U... z : divided by 2. :Implicit output of resulting array.  • I think you can change SpUl to... wait, nevermind :( You can save a byte though by replacing (V-X with XnV, if I'm not mistaken. – ETHproductions Jun 22 '17 at 1:08 • Oh, yeah, forgot about n; thanks @ETHproductions. – Shaggy Jun 22 '17 at 9:07 PHP, 113 bytes: for([,$s,$n]=$argv;$i++<$n;)for(print($f=str_pad)(" ",($n-$i)*strlen($s)/2+!$p=0);~$c=$s[$p++];)echo$f($c,$i,$c);


Run with php -nr '<code>' '<string>' <N> or test it online.

breakdown

# import input, loop $i from 1 to$n
for([,$s,$n]=$argv;$i++<$n;) # 1. print newline and padding, reset$p
for(print($f=str_pad)("\n",($n-$i)*strlen($s)/2+!$p=0); # 2. loop$c through string
~$c=$s[$p++];) # print repeated character echo$f($c,$i,c);  CJam, 36 bytes l_,2/:T;]li:F{[_U)*zSTFU)-**\N]\}fU;  Try it online! • Welcome to PPCG! Nice first submission :) – HyperNeutrino Jun 21 '17 at 18:20 • @HyperNeutrino Well, I have a feeling my code is pretty far from optimized, but... thanks. :) – Siguza Jun 21 '17 at 18:25 • But it contains STFU :-D – Luis Mendo Jun 21 '17 at 23:21 T-SQL, 223 bytes DECLARE @ char(99),@n INT,@i INT=1,@j INT,@p varchar(max)SELECT @=s,@n=n FROM t R:SET @j=0SET @p=SPACE((@n-@i)*len(@)/2)C:SET @j+=1SET @P+=REPLICATE(SUBSTRING(@,@j,1),@i)IF @j<LEN(@)GOTO C PRINT @p SET @i+=1IF @i<=@n GOTO R  Input is via pre-existing table t with columns s and n, per our IO standards. Not much to explain, it's a pretty straightforward nested loop, using @i for the rows and @j to walk through the characters of the string which are REPLICATED @i times: DECLARE @ char(99),@n INT,@i INT=1,@j INT,@p varchar(max) SELECT @=s,@n=n FROM t R: SET @j=0 SET @p=SPACE((@n-@i)*len(@)/2) C: SET @j+=1 SET @P+=REPLICATE(SUBSTRING(@,@j,1),@i) IF @j<LEN(@)GOTO C PRINT @p SET @i+=1 IF @i<=@n GOTO R  R, 125 95 bytes function(S,n)for(i in 1:n)cat(rep(' ',(n-i)/2*nchar(S)),rep(el(strsplit(S,'')),e=i),sep="",' ')  Try it online! Explanation: It's pretty straightforward, splitting the string and repeating the elements i times each rep(s,e=i) (e is short for each) as we loop. The tricky part is rep('',(n-i)/2*length(s)+1). This is the padding string, but it's a bunch of empty strings. I need to add 1 because otherwise the result is character(0), a zero-length vector, and cat, which by default separates its elements with spaces, misaligns the final line. Mathematica, 97 bytes (c=Characters@#;T=Table;Column[T[""<>T[""<>T[c[[i]],j],{i,Length@c}],{j,#2}],Alignment->Center])&  input ["o-o o-o", 10] Tcl, 143142141 138 bytes proc p s\ n {set p [expr [set w [expr [string les]/2]]*$n];time {incr p$w;puts [format %$p\s [regsub -all .$s [append r \\0]]]} $n;cd}  Test: % p "o-o o-o" 5 o-o o-o oo--oo oo--oo ooo---ooo ooo---ooo oooo----oooo oooo----oooo ooooo-----ooooo ooooo-----ooooo  Remark: the "cd" at the end of the procedure prevents time's result to be printed out below the pyramid, but changes the current directory - a side effect that's not explicitly forbidden. Thanks to sergiol for a hint to save one byte.... and another hint to save one more byte. Thanks to aspect (on tcl chat) for another 3 bytes saved! Swift, 232 bytes Probably could be better, but I don't have much time to refactor. This answer uses Swift 4, so it can't currently be run online. var p:(String,Int)->String={s,i in let r=(1...i).map{n in return s.map{return String(repeating:$0,count:n)}.joined()};return(r.map{return String(repeating:" ",count:(r.last!.count-$0.count)/2)+$0}as[String]).joined(separator:"\n")}


LOGO, 97 95 bytes

to f :s :n
for[i 1 :n][repeat(:n-:i)/2*count :s[type "\ ]foreach :s[repeat :i[type ?]]pr "]
end


Try the code on FMSLogo interpreter.

Define a function f which takes two inputs, :s and :n, then print the result.

Java 8, 164 148 bytes

s->n->{String o="";for(int i=0,m,j;i++<n;){o+="\n";for(m=0;m++<(n-i)*s.length()/2;)o+=" ";for(char c:s.toCharArray())for(j=0;j++<i;)o+=c;}return o;}


Explanation:

s->n->{
String o = "";                                  //empty output string
for (int i = 0, m, j; i++ < n; ) {              //for each row
o += "\n";                                  //append a new line
for (m = 0; m++ < (n - i)*s.length()/2; )   //for amount of spaces = inversed row_number * half length
o += " ";                               //append a space
for (char c : s.toCharArray())              //for each char of the string
for (j = 0; j++ < i; )                  //row_number times
o+=c;                               //append char
}
return o;
}


Rust, 107 bytes

|a:&str,b|for i in 0..b{println!("{:^1$}",a.split("").map(|s|s.repeat(i+1)).collect::<String>(),a.len()*b)}  playpen link Defines an anonymous function that takes a string slice and number, printing the wanted pattern to standard output. It assumes that the string slice only contains ASCII characters, but the challenge never specifies that full unicode support is necessar. To be correct for unicode as well would require 117 bytes: |a:&str,b|for i in 0..b{println!("{:^1$}",a.split("").map(|s|s.repeat(i+1)).collect::<String>(),a.chars().count()*b)}


The explanation is rather simple:

|a:&str,b|                             // arguments, compiler can't infer the type of a unfortunately
for i in 0..b {                    // iterate from row 0 to row b - 1
println!(
"{:^1\$}",                  // print a line containing arg 0, centered with the width specified as arg 1
a.split("")                // split the string into slices of one character
.map(|s|s.repeat(i+1)) // for each slice, yield a string containing row+1 times that slice
.collect::<String>(),  // concatenate each of the strings into one string
a.len()*b                  // total length should be the length of the string times the amount of rows
)
}


SOGL V0.12, 8 bytes

∫dč*∑}¹╚


Try it Here!

Explanation:

∫dč*∑}¹╚
∫    }    iterate over 1..input, pushing counter
d        push the variable D, which sets itself to the next input as string
č       chop into characters - a vertical array
*      multiply horizontally by the counter
∑     join the array together
¹   wrap all that in an array
╚  center horizontally


I didn't feel like updating my old answer here as it uses a different method and uses a new(er than the challenge) feature - ╚

Python 2, 79 77 bytes

s,n=input();m=n
while m:m-=1;print' '*(m*len(s)/2)+''.join(i*(n-m)for i in s)


Try it online!

Edit: -2 bytes courtesy @FlipTack

• You can remove the square brackets around [i*(n-m)for i in s], as .join is capable of taking a generator, which should ave you two bytes. – FlipTack Dec 28 '17 at 18:44

Excel VBA, 98 Bytes

Anonymous VBE immediate window function that take input as string from [A1] and int from [B1] then outputs to the VBE immediate window

For i=1To[B1]:?Spc([Len(A1)/2]*([B1]-i));:For j=1To[Len(A1)]:?String(i,Mid([A1],j,1));:Next:?:Next