In sporting competitions, it often happens that winners are presented on podiums, with the first-place person on the highest in the middle, the second-place person on the middle height to the left, and the third-place person on the lowest and to the right. We're going to recreate that here with some special tweaks.

The podiums are presented below:

     | @ |
@---@| | |
| @ || | |
| | || | |@---@
| | || | || @ |

This will form the basis for this challenge. The next step is to make the podiums wide enough to fit the people (printable ASCII strings) that are on them. However, we want to ensure aesthetic beauty (because this is a fantastic photo opportunity), so each podium needs to be the same width, and the width must be odd. Additionally, the people will (obviously) want to stand in the center of the podium, so the strings must be centered as best as possible. (You can align to either the left or the right, and it doesn't need to be consistent.) The above podiums are the minimum size, and are considered 3 wide.

For example, given the input ["Tom", "Ann", "Sue"] representing first-, second-, and third-place respectively, output the following podiums:

 Ann | @ |
@---@| | |
| @ || | | Sue
| | || | |@---@
| | || | || @ |

However, if we have Anne instead of Ann, we'll need to go up to the next size, 5, and center the strings as best as possible. Here, I'm aligning so the "extra" letter of Anne is to the left of center, but you can choose which side to align to.

 Anne  |  @  |
@-----@|  |  |
|  @  ||  |  |  Sue
|  |  ||  |  |@-----@
|  |  ||  |  ||  @  |

Let's go for some longer names. How about ["William", "Brad", "Eugene"]:

  Brad   |   @   |
@-------@|   |   |
|   @   ||   |   | Eugene
|   |   ||   |   |@-------@
|   |   ||   |   ||   @   |

Here we can see that Brad has a lot of whitespace, Eugene less so, and William fits just right.

For a longer test case, how about ["A", "BC", "DEFGHIJKLMNOPQRSTUVWXYZ"]:

           BC            |           @           |
@-----------------------@|           |           |
|           @           ||           |           | DEFGHIJKLMNOPQRSTUVWXYZ
|           |           ||           |           |@-----------------------@
|           |           ||           |           ||           @           |

Finally, we have the smallest possible input, something like ["A", "B", "C"]:

  B  | @ |
@---@| | |
| @ || | |  C
| | || | |@---@
| | || | || @ |

  • Input and output can be given by any convenient method.
  • The input is guaranteed non-empty (i.e., you'll never receive "" as a name).
  • You can print it to STDOUT or return it as a function result.
  • Either a full program or a function are acceptable.
  • Any amount of extraneous whitespace is acceptable, so long as the characters line up appropriately.
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.
  • \$\begingroup\$ Do all even-length names have to be aligned in the same direction? \$\endgroup\$ – Sparr Feb 21 at 0:42
  • 1
    \$\begingroup\$ Why do the podiums in the last example output have length 3 instead of length 1? \$\endgroup\$ – bruderjakob17 Feb 21 at 13:33
  • 3
    \$\begingroup\$ @bruderjakob he states at the beginning "the podiums above are the minimum size and are considered 3 wide" \$\endgroup\$ – rtpax Feb 21 at 13:36

13 Answers 13


JavaScript (ES8), 196 bytes

332`.replace(/./g,n=>[...`@-@   |@||||`.substr(n*3,3)].join(' -'[+!+n].repeat(m/2))||a[n-=4].padStart(m+l[n]+3>>1).padEnd(m+3),m=Math.max(2,...l=a.map(s=>s.length))&~1)

Try it online!


Groovy, 187, 176, 156, 150 bytes

f={n->m=n*.size().max()|1;h=' '*(m/2);'30734715746756276647665'*.toLong().sum{(n*.center(m+2)+[' '*(m+2),"@${'-'*m}@","|$h@$h|","|$h|$h|",'\n'])[it]}}

Try it online!

(note: the tio groovy interpreter could not handle indexing Lists using Long values even though groovy 2.5.6 can. Thus the tio answer is using *.toShort() instead of *.toLong() which adds a byte)

Defines a closure f which can be called via:


where f returns a string.


Unobfuscating the code, we have:

  h=' '*(m/2)
  a=n*.center(m+2)+[' '*(m+2),"@${'-'*m}@","|$h@$h|","|$h|$h|",'\n']
  • f={n-> - define closure f with one in-param n
  • m=n*.size().max()|1 - find max name len, binary-or to odd number
  • h=' '*(m/2) - h will contain floor(m/2) spaces, used later
  • a=...- creates an encoding list with elements:
    • indexes 0,1,2 - names, centered to max len
    • index 3 - m+2 spaces
    • index 4 - @---@ pattern, padded to len
    • index 5 - | @ | pattern, padded to len
    • index 6 - | | | pattern, padded to len
    • index 7 - newline
  • '307...'*.toLong().sum{a[it]}- use indicies into the encoding list to build the result. .sum uses the fact that string + string in groovy is valid.
  • note that the expression '3073...'*.toLong() uses the *. spread operator to call toLong() on each character, returning a list of numbers.
  • note in the answer the variable a has been inlined,nelines removed etc.

Canvas, 45 bytes

r351⁰{|*@;∔;J└l2M2%±├ ××l⇵╷-×└+-α∔k+│∔⇵;}┐++⇵

Try it here!


r    Center the input, preferring left. Converts to an ASCII-art object
     which pads everything with spaces. This is the bulk of the magic.

 251⁰{ .... }            for each number in [2, 5, 1]:
      |*                 repeat "|" vertically that many times
        @;∔              prepend an "@" - a vertical bar for later
           ;             swap top 2 stack items - put the centered art on top
            J            push the 1st line of it (removing it from the art)
             └           order the stack to [remaining, "@¶|¶|..", currentLine]
              l          get the length of the current line
               2M        max of that and 2
                 2%      that % 2
                   ±├    (-that) + 2
                      ×× prepend (-max(len,2)%2) + 2 spaces
l                 get the length of the new string
 ⇵╷               ceil(len / 2) -1
   -×             repeat "-" that many times - half of the podiums top
     └            order stack to [art, currLine, "@¶|¶|..", "----"]
      +           append the dashes to the vertical bar = "@-----¶|¶|.."
       -α∔        vertically add "-" and the original vertical bar - "-¶@¶|¶|.."
          k       remove the last line of that to make up for the middles shortness
           +      and append that horizontally - half of the podium without the name
            │     palindromize the podium
             ∔    and prepend the name
              ⇵   reverse vertically so the outputs could be aligned to the bottom
               ;  and get the rest of the centered input on top
┐     remove the useless now-empty input
 ++   join the 3 podium parts together
   ⇵  and undo the reversing

Abuses "and it doesn't need to be consistent", making it pretty unintelligible.

  • \$\begingroup\$ Umm...any chance of an explanation? \$\endgroup\$ – Matias Bjarland Feb 20 at 22:43
  • 1
    \$\begingroup\$ @MatiasBjarland though it's mostly stack manipulation and the rest i barely understand, there. \$\endgroup\$ – dzaima Feb 20 at 23:05

Python 2, 197 190 bytes

x,y,s='@| '
for l in-~W*s+a,s*W+A,s+b+s+B,A+C,B+C+s+c,C+C+A,C+C+B:print l

Try it online!

-6 bytes, thanks to Andrew Dunai

  • \$\begingroup\$ You can save 6 bytes by replacing line 5 to x,y,p='@| ' and using p instead of ' ' \$\endgroup\$ – Andrew Dunai Feb 21 at 19:01
  • 1
    \$\begingroup\$ @andrewdunai thanks :) \$\endgroup\$ – TFeld Feb 21 at 21:50

Python 2, 157 bytes

while i:print''.join(([a[k/2]]+list('-@||||    '))[7-i-k].center(max(map(len,a))|1,'- '[i+k!=6]).join('@ |'[cmp(i+k,6)]*2)for k in(2,0,4));i-=1

Try it online!


Charcoal, 63 bytes


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


Calculate the number of spaces in each half of a podium.


Loop over each place. Note that input is expected to be in the order 2nd, 1st, 3rd.


Position to the start of the line that will have the text.


Output the text with enough left padding to centre it.


Get the height of the podium.


Draw the podium.

Alternative approach, also 63 bytes:

≔÷⌈EθLι²ηF³«J×ι⁺³⊗η⊗﹪⁻¹ι³⟦◧§θι⁺⊕η⊘⊕L§θι⪫@-@×-η⟧E⁻⁷ⅉ⪫⪫||§|@¬κ× η

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


Calculate the number of spaces in each half of a podium.


Loop over each place. Note that input is expected to be in the order 2nd, 1st, 3rd.


Position to the start of the line that will have the text.


Output the text with enough left padding to centre it.


Also output the top of the podium by inserting -s between the characters of the string @-@ to reach the correct width.

E⁻⁷ⅉ⪫⪫||§|@¬κ× η

Print the remainder of the podium by spacing the |s appropriately, except that the middle character is a @ on the first row.


R 308 302 299

-6 bytes thanks to @JAD
-3 bytes thanks to @Guiseppe, now I'm under 300

g=' '
a=lapply(a,function(q){r=nchar(q);l=(e-r)/2+1;if(r%%2<1)c(g~l,q,g~l+1)else c(g~l,q,g~l)})

There's probably a better way to create the layout; I should try what options I have for data frames.

Try it online

  • \$\begingroup\$ 304 bytes \$\endgroup\$ – JAD Feb 21 at 13:58
  • 2
    \$\begingroup\$ hats off to ya for doing a variable ascii-art challenge in R...never fun to do. You can save 3 bytes by using i=max(1,nchar(a)%/%2). Generating a matrix and using write might be shorter (rather than a data.frame). I suggest using format with j="c" to auto-justify things, and strrep is a helpful one in this case as well. Maybe try the golfR chatroom to bounce ideas off? \$\endgroup\$ – Giuseppe Feb 21 at 20:40
  • \$\begingroup\$ Yeah, I didn't realize how hard it would be going into it. I learned a bit tho, mostly I should learn Python better, or start learning Perl :). I'd forgotten about strrep; I'll have to look into that. \$\endgroup\$ – CT Hall Feb 21 at 22:46

Clean, 209 bytes

import StdEnv,Data.List
k=[' @|||||']
$l#m=max(maxList(map length l))3/2*2+1
=flatlines(transpose[(spaces(n*2)++g)%(0,6)\\n<-[1,0,2],g<-[k:[[c,'-':tl if(i==m/2)k['  '..]]\\c<-cjustify m(l!!n)&i<-[0..]]]++[k]])

Try it online!


Python 2, 188 bytes

s=max(map(len,l))/2or 1
D=(' '*s).join
for l in' '*S+d(a,S),' '*S+A,d(b,S)+C,A+D,C+D+d(c,S),D+D+A,D+D+C:print l

Try it online!

-5 thanks to TFeld.


Go, 436 bytes

Go is terrible for golf. But:

package main;import ("fmt";"os");func main(){;z:=os.Args;f:=3;for i:=1;i<4;i++{;if len(z[i])>f{;f=len(z[i]);};};f+=1-f%2;p:=(f-1)/2+1;b:="@";for j:=0;j<f;j++{;b+="-";};b+="@";x:=fmt.Sprintf("|%*v%*v",p,"@",p,"|");y:=fmt.Sprintf("|%*v%[1]*v",p,"|");fmt.Printf("%*v%*v\n%*v%v\n%*v%*v\n%v%v\n%v%v%*v\n%v%v%v\n%v%v%v",f+2,"",p+1+len(z[1])/2,z[1],f+2,"",b,p+1+len(z[2])/2,z[2],2*f+3-p-len(z[2])/2,x,b,y,x,y,p+1+len(z[3])/2,z[3],y,y,b,y,y,x)}

Broken down:

package main
import (
func main() {
  for i:=1;i<4;i++{
    if len(z[i])>f{
  for j:=0;j<f;j++{


Java 8, 399 394 373 Bytes

This solution is probably way too long, but it is a solution :)

static String r(String[]p){String s="";int l[]=new int[]{p[0].length(),p[1].length(),p[2].length()},m=Math.max(l[0],Math.max(l[1],l[2]))+2,i,q,j,a,k,t;if(m%2==0)m++;if(m==3)m=5;for(i=0;i<7;i++){for(q=0;q<3;q++)for(j=0;j<m;j++){a=(2*q+1)%3;k=2*a;t=(m-l[a])/2;s+=i==k?j>=t&j<t+l[a]?p[a].charAt(j-t):" ":i==k+1?j%(m-1)==0?"@":"-":i>=k+2?j%(m-1)==0?"|":j==m/2?i==k+2?"@":"|":" ":" ";}s+="\n";}return s;}

Saved 5 Bytes by directly iterating in order (a=1,0,2 instead of q=0,1,2; a=f(q))

static String r(String[]p){String s="";int l[]=new int[]{p[0].length(),p[1].length(),p[2].length()},m=Math.max(l[0],Math.max(l[1],l[2]))+2,i,j,a,k,t;if(m%2==0)m++;if(m==3)m=5;for(i=0;i<7;i++){for(a=1;a<4;a=a==1?0:a+2)for(j=0;j<m;j++){k=2*a;t=(m-l[a])/2;s+=i==k?j>=t&j<t+l[a]?p[a].charAt(j-t):" ":i==k+1?j%(m-1)==0?"@":"-":i>=k+2?j%(m-1)==0?"|":j==m/2?i==k+2?"@":"|":" ":" ";}s+="\n";}return s;}

Saved 21 Bytes thanks to @KevinCruijssen:

static String r(String[]p){String s="";int l[]=new int[3],m=0,i,j,a,k,t;for(String x:p)l[m++]=x.length();m=Math.max(l[0],Math.max(l[1],l[2]))+2;m+=m%2<1?1:m==3?2:0;for(i=0;i<7;i++,s+="\n")for(a=1;a<4;a=a==1?0:a+2)for(j=0,k=2*a,t=(m-l[a])/2;j<m;j++)s+=i==k?j>=t&j<t+l[a]?p[a].charAt(j-t):" ":i==k+1?j%~-m<1?"@":"-":i>=k+2?j%~-m<1?"|":j==m/2?i==k+2?"@":"|":" ":" ";return s;}

As @KevinCruijssen suggested, one could also use var instead of String in Java 10+ and save some extra Bytes. I don't do this for the simple reason that I don't have Java 10 yet :D also, lambdas could be used. But this would only reduce the amount of bytes if we would leave out assigning it to a Function<String[],String> variable.

In expanded form:

static String r(String[]p){
    String s=""; //The string that will be returned
    int l[]=new int[3], //An array containing the lengths of our three names
            m=0, //tmp variable for filling l
            i,j,a,k,t; //some declarations to save a few bytes lateron
    for(String x:p) l[m++]=x.length();
    m+=m%2<1? //ensure odd length of the podests
        :m==3?2:0; //ensure the length is at least 3 (in my code, m is the length of the podests + 2)
    for(i=0;i<7;i++,s+="\n") //iterate by row
        for(a=1;a<4;a=a==1?0:a+2) //iterate by place: a=1,0,2
            for(j=0,k=2*a,t=(m-l[a])/2;j<m;j++) //iterate by column
                //k is the row number from top in which the a-th name goes
                //t is the column at which the name starts
                //now, append the right char:
                s+=i==k? //write the name
                        :" "
                    :i==k+1? //write the top of the podest ("@---@")
                    :i>=k+2? //write the bottom of the podest ("|  |@  |")
                        j%~-m<1? //the left and right edge of the podest
                            :j==m/2? //the center of the podest
                                i==k+2? //are we at the first row of the bottom?
                                    "@" //the case where we have to write "| @ |"
                                    :"|" //the case "| | |"
                                :" "
                        :" "
    return s;

The input has to be given as String-array of length 3. An example looks like this:

public static void main(String[] args){
    System.out.print(r(new String[]{"Anthony", "Bertram", "Carlos"}));


 Bertram |   @   |         
@-------@|   |   |         
|   @   ||   |   | Carlos  
|   |   ||   |   |@-------@
|   |   ||   |   ||   @   |
  • 1
    \$\begingroup\$ Nice answer, and welcome to PPCG! +1 from me! Here some basic things to golf to make it 342 bytes: Java 8+ lambda instead of regular method; Java 10+ var instead of String; filled the length-array with a for-each loop; changed if(m%2==0)m++;if(m==3)m=5; to m+=m%2<1?m==2?3:1:0 for the same effect; changed all %nr==0 to %nr<1; changed the %(m-1) to %~-m; put everything inside the loop itself so the brackets {} can be removed. \$\endgroup\$ – Kevin Cruijssen Feb 21 at 14:49
  • \$\begingroup\$ If you haven't seen it yet, Tips for golfing in Java and Tips for golfing in <all languages> might both be interesting to read through. Enjoy your stay! \$\endgroup\$ – Kevin Cruijssen Feb 21 at 14:50
  • \$\begingroup\$ @KevinCruijssen alright, thank you very much! I'll update the post! \$\endgroup\$ – bruderjakob17 Feb 21 at 14:53

PHP, 147 bytes

golfed 93 bytes off my initial idea, a straight forward <?=:

for(;~$v=_616606256046543440445[++$i];)echo$b="@   || "[$v],str_pad(($v&4?"|@":$argv)[$v&3],max(array_map(strlen,$argv))," -"[!$v],2),$b,"

takes names from command line arguments. Run with -nr or try it online.
Requires PHP 7; yields warnings in PHP 7.2 (and later, presumably). See the TiO for a +5 byte fix.


0:@---@     = top border
1,2,3       = $argv with spaces
4: "| | |"  = default
5: "| @ |"  = below top
6: "     "  = empty


for(;~$v=_616606256046543440445[++$i];)echo # loop through map:
    $b="@   || "[$v],                       # print left border
    str_pad(                                # print padded string:
        ($v&4?"|@":$argv)[$v&3],                # string to be padded
        max(array_map(strlen,$argv)),           # pad length = max argument length
        " -"[!$v],                              # pad with: dashes if top border, spaces else
        2                                       # option: center text (pad on both sides)
    $b,                                     # print right border
    "\n"[$i%3]                              # add linebreak every three items

The pre-increment for $i saves me from any tricks for the newlines.
The blank for 6 can also be empty; so I did that.
But using $argv[0] for the top border string - was the nicest golf ever. (and saved 9 bytes!)


C(GCC) 302 293 292 289 287 bytes

-6 byte thanks to ceilingcat

#define P(h,n)r=w+2-L[n];i/h?printf("%*s%*s%*s",-~r/2,D,L[n],i>h?D:N[n],r/2,D):printf(~i/h?"@%s@":"|%*s%c%*s|",~i/h?D+1:w/2,D,i>h-3?64:'|',w/2,D);
f(int**N){char L[3],w=3,i=3,r,D[99]={};for(;i--;)w=w<(L[i]=strlen(N[i]))?L[i]|1:w;memset(D+1,45,w);for(i=7;i--;puts(D)){P(4,1)P(6,0)P(2,2)}}

Run it here

Ungolfed and explained (technically you can't have comments after back slashes in macros, so this won't run)

#define P(h,n)\
    r=w+2-L[n];\ //get leftover width
    i/h?\ //if i >= h
        printf("%*s%*s%*s",-~r/2,D,L[n],i>h?D:N[n],r/2,D):\//if too high print all spaces, otherwise center the name
//if (i == h - 1) print top row using D calculated if row right below top, else print '@'(64) in center, otherwise '|'
        L[3],//lengths of each string
        w=3,//width (init to minimum)
        i=3,//index, used in for loops
        l,//left padding
        r,//right padding
        D[99]={};//string of '-' of correct length (max 99) but first char is null for empty string
    for(;i--;)//i was set to 3 before, i will be {2,1,0}
        w=w<(L[i]=strlen(N[i]))?//set length to str len and compare to longest width so far
            L[i]|1://set it to length if longer, but make sure it is odd
            w;//do not replace
    memset(D+1,45,w); //set the first w bits of D to '-', leaves a null terminator
    for(i=7;i--;puts(D)){//i will be {6...0}
        P(4,1)//print second place, 4 high
        P(6,0)//print first place, 6 high
        P(2,2)//print thrid place, 2 high

Here is the calling code

int main()
  char* N[3] = {"Tom", "Anne", "Sue"} ;

and output

  Anne |  @  |       
@-----@|  |  |       
|  @  ||  |  |  Sue  
|  |  ||  |  |@-----@
|  |  ||  |  ||  @  |
  • \$\begingroup\$ Suggest for(;i--;memset(D+1,45,w))w=w<(L[i]=strlen(N[i]))?L[i]|1:w; instead of for(;i--;)w=w<(L[i]=strlen(N[i]))?L[i]|1:w;memset(D+1,45,w); \$\endgroup\$ – ceilingcat Apr 8 at 1:47

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.