Your program gets a text as an input, at least 8 characters long, and always consisting of even number of characters. (no need to evaluate correctness of input).

Your goal is to display that text as a rectangle. For example, given HelloWorld as an input, display

d  o


  • Text goes around clockwise (starting position as you like)
  • It will form a closed rectangle, sides 1 character wide.
  • The rectangle will have to encompass the most area inside. (just to rule out the trivial answer of displaying the text in two lines)
  • No other characters are printed besides the text itself and the necessary padding spaces and line feeds.

As code-golf, shortest code wins.

Winner is selected not sooner than 10 days after first valid answer.


16 Answers 16


PostScript 50 binary, 113 ASCII

This uses graphical output. Hexdump of the program using binary tokens:

$ hexdump -C textRect_binary.ps 
00000000  74 5b 30 20 39 5b 74 92  62 34 92 36 92 38 92 10  |t[0 9[t.b4.6.8..|
00000010  32 92 19 5d 7b 92 2c 7b  32 92 19 7d 92 83 92 3e  |2..]{.,{2..}...>|
00000020  92 6e 7d 92 49 5d 39 20  39 92 6b 91 c7 39 92 8e  |.n}.I]9 9.k..9..|
00000030  92 c3                                             |..|

Download to try it. Using Ghostscript, the to-be-rendered text can be passed to the program as follows:

gs -st=helloworld textRect_binary.ps 

Graphical output looks like this:

rendered output

The same code using ASCII tokens looks like this:

t[0 9[t length
4 div dup
2 copy]{cvi{2 copy}repeat
exch neg}forall]9 9 moveto/Courier 9 selectfont

The strategy is to use xyshow for defining where we move after showing each character before showing the next character. We're starting in the lower left corner, moving clockwise, i.e. first up, then right, then down then left. We're always moving 9 units, so first we have a relative movement of 0 9, then 9 0, then 0 -9, then -9 0. We can get from one pair of these numbers to the next with the sequence exch neg.

We need to build an array for xyshow that holds these pairs of numbers, one pair for each character. This means, if we have helloworld as example string, which has 10 characters, we want to go up twice, then right thrice, then down twice and left thrice. We get these values (two and three) by dividing the string length by 8, once rounding to the floor, once to the ceiling.

So, we copy 0 9 twice, then switch to the relative x/y coordinates using exch neg, copy those thrice and so on.

This commented code shows what happens on the stack:

t[0 9                % t [ 0 9
[t length            % t [ 0 9 [ length
4 div dup            % t [ 0 9 [ length/4 length/4
ceiling              % t [ 0 9 [ length/4=height width
2 copy]              % t [ 0 9 [height width height width]
{%forall             % t [ 0 9 ... x y height_or_width
  cvi                % t [ 0 9 ... x y height_or_width_integer
  {2 copy}           % t [ 0 9 ... x y height_or_width_integer {2 copy}
  repeat             % t [ 0 9 ... x y .. x y
  exch neg           % t [ 0 9 ... x y .. y -x
}forall]             % t [0 9 ... -9 0]
9 9 moveto/Courier 9 selectfont
  • \$\begingroup\$ +1 holy bajeezus. I'm seriously deficient in my knowledge of level-2 and beyond. \$\endgroup\$ Commented Jan 20, 2013 at 6:51
  • \$\begingroup\$ You mean xyshow? Happy to introduce you to this one--some time ago you introduced me to kshow, which I wasn't really aware of ;-). \$\endgroup\$
    – Thomas W.
    Commented Jan 20, 2013 at 7:22
  • \$\begingroup\$ @luserdroog: BTW: I'm pretty proud that the current GolfScript entry has more than 10% more characters than my binary entry, but it bugs me that my ASCII version is one character away from a draw with Ruby (actually, even three, because the Ruby code could be golfed further). Do you have any ideas for further optimization? \$\endgroup\$
    – Thomas W.
    Commented Jan 20, 2013 at 10:51
  • \$\begingroup\$ @ThomasW. Now my GolfScript entry is 24% shorter than your binary ;-) And I still think there is still the chance to shorten it even further by one or two chars. \$\endgroup\$
    – Howard
    Commented Jan 24, 2013 at 20:31
  • \$\begingroup\$ @Howard: Argh!!! Can anyone ever beat GolfScript? \$\endgroup\$
    – Thomas W.
    Commented Jan 24, 2013 at 21:08

Ruby 112 100

I'm new to Ruby and this is my first code golf. I drew upon memowe's perl implementation and tried to make a Ruby version of it. This is 112 100 characters and assumes you assign a string to x. Looking forward to seeing others.

puts x[0..w=l/2-h=l/4]
1.upto(h-1){|i|puts x[-i]+' '*(w-1)+x[w+i]}
puts x[w+h..l-h].reverse

Edited to implement suggestions. I think it's 100 characters now. Thanks guys!

  • \$\begingroup\$ Nice! You can save two chars in the 5th line (remove spaces). \$\endgroup\$
    – Thomas W.
    Commented Jan 19, 2013 at 21:00
  • \$\begingroup\$ I like it. Thanks. Looks good that Ruby strings can be accessed like an array, I had to built one by myself. :) \$\endgroup\$
    – memowe
    Commented Jan 20, 2013 at 14:16
  • \$\begingroup\$ You could replace x.length with x.size (Saves 2 characters) \$\endgroup\$
    – knut
    Commented Jan 20, 2013 at 22:22
  • 1
    \$\begingroup\$ And 8 more using puts x[0..w=l/2-h=l/4]. \$\endgroup\$
    – Howard
    Commented Jan 24, 2013 at 20:34

GolfScript, 56 53 40 38 characters

1/..,4/):l<n@l>{)" "l*2>@(n@.,l-}do-1%

You may test the script online.


Perl (124 118 109+3=112)

This formerly was pretty straightforward. Counted all command line options as 1 character each.



$ perl -nlE '$w=(@s=split//)/2-($h=int@s/4);say@s[0..$w--];say$s[1-$_].$"x$w.$s[$w+$_]for+2..$h;say+reverse@s[@s/2..@s-$h]'
z      i
y      j
x      k
w      l
v      m
  • \$\begingroup\$ This can be compacted: (1) (@s-$h*2)/2 == @s/2-$h (2) $w can be represented as $w=(@s=split//)/2-($h=int@s/4);, thus saving two semicolons \$\endgroup\$
    – amon
    Commented Jan 20, 2013 at 4:18
  • \$\begingroup\$ Updated the code. \$\endgroup\$
    – memowe
    Commented Jan 20, 2013 at 14:14
  • \$\begingroup\$ Further interesting stuff: (1) the space is the default value of the array interpolation var $"–saves 1 char. (2) $w+$h == @s/2–saves 1 char. (3) If $w is smaller by one, we can simplify $"x($w-1). For this, the $_ has to be increased by 1. Saves like 3 chars. (4) The final semicolon is überflüssig, saves 1 char. This leads to the code fragment say@s[0..$w--];say$s[1-$_].$"x$w.$s[$w+$_]for+2..$h;say+reverse@s[@s/2..@s-$h] (with a few + for fun, so there isn't a single space left). \$\endgroup\$
    – amon
    Commented Jan 20, 2013 at 19:31
  • \$\begingroup\$ Excellent golfification, @amon, would you edit it in my post please? That way the world can see who did it. :) \$\endgroup\$
    – memowe
    Commented Jan 20, 2013 at 20:34

Brainfuck - 194 187

  • \$\begingroup\$ Nice try, but it does not work. The bottom line is in the wrong direction, contrary to rule 1, and it only has a fixed height, contrary to rule 3. \$\endgroup\$
    – vsz
    Commented Jan 20, 2013 at 19:04
  • \$\begingroup\$ Not sure why I flipped the last row. I totally had it in mind the correct way as I was writing it. The fix actually saves 7 commands. I did cop out on the fixed height thing, but its not the trivial, 2 line case you talked about. Maybe I'll make it better in the future. \$\endgroup\$
    – captncraig
    Commented Jan 22, 2013 at 3:05

Mathematica 156 199 344

Edit : This is a major rewrite of earlier code. It works essentially the same, but now takes as input a string of length < 120 chars and automatically sizes the square.

It could still be golfed a bit but will not get down to the size of the earlier, and buggier, versions.

f@s_ := ({a, t, w, q} = {Automatic, Text, Quotient[StringLength@s, 2],
 Quotient[StringLength[s], 4] + 1};z = StringSplit[StringInsert[s <> ConstantArray[" ", 0],
 "*", {q, 2 q, 3 q}], "*"];
Graphics[{t[z[[1]], {0, q}],t[z[[2]], {q, 0}, a, {0, -1}],t[z[[3]], {0, -q}, a, {-1, 0}],
t[z[[4]], {-q, 0}, a, {0, 1}]},ImageSize -> 500,BaseStyle -> {FontFamily -> "Courier", 21},
PlotRange -> 34,ImagePadding -> 22])


f["Hello Code Golf World!"]
f["January, February, March,April, May, June, July"]
f["This text is normal, this goes downwards,this is upside-down, and this is upwards"]




  • \$\begingroup\$ Hey, an array of strings? That's really bending the rules, isn't it? \$\endgroup\$
    – Thomas W.
    Commented Jan 20, 2013 at 0:03
  • \$\begingroup\$ @ThomasW. The comments in the answer indicate it's not a final solution. \$\endgroup\$
    – kojiro
    Commented Jan 20, 2013 at 0:48
  • \$\begingroup\$ Ah, I see! Wonder whether I should take the challenge and try something similar in PostScript... \$\endgroup\$
    – Thomas W.
    Commented Jan 20, 2013 at 10:47
  • \$\begingroup\$ I like how it looks now! \$\endgroup\$
    – Thomas W.
    Commented Jan 21, 2013 at 19:30
  • \$\begingroup\$ @Thomas W. Thanks. Getting the format to look right for a wide range of string lengths cost a lot of bytes. \$\endgroup\$
    – DavidC
    Commented Jan 21, 2013 at 20:41

Perl + Regexes: 104 (101+3)

(counting code + switches)

Here is a solution using nice Regexes, and a bit of Perl:

perl -plE'$w=($l=length)/2-($h=int$l/4);s/..{$w}\K.*/"\n".reverse$&/e;$"x=--$w;s/.\K(.*)(.)$/$"$2\n$1/while--$h'

This will only operate correctly on one input line.

Inspired by memowe, but essentially without any arrays.

  • \$\begingroup\$ Sorry for the dumb question: How can I try this out? I'm pasting your code to the command line, then type something, press enter and something comes out. But it's not a box. What am I doing wrong? \$\endgroup\$
    – Thomas W.
    Commented Jan 21, 2013 at 22:15
  • \$\begingroup\$ @ThomasW. It seems to work for me, for an arbitrary even number of chars. The above code is guaranteed to work under bash and perl version 5.12+. Input is accepted via STDIN, and only the first line is processed correctly. I don't know how to quote the code correctly for cmd.exe. \$\endgroup\$
    – amon
    Commented Jan 22, 2013 at 13:44
  • 1
    \$\begingroup\$ Ah, was probably my mistake. I probably used a string of odd length. This works: echo thisworksgreat | perl -plE'$w=($l=length)/2-($h=int$l/4);s/..{$w}\K.*/"\n".reverse$&/e;$"x=--$w;s/.\K(.*)(.)$/$"$2\n$1/while--$h' \$\endgroup\$
    – Thomas W.
    Commented Jan 22, 2013 at 13:59

PostScript (106)

This is inspired by dude's Mathematica solution.

0{= =
4 add dup
t length mod 4
lt{-90 rotate}if}0[0 3 -3 0 9 9]concat
0 moveto/Courier 5 selectfont
t kshow

With Ghostscript call this like

gs -st=hello! boxtext.ps

It produces output like.



It uses kshow to show the glyphs one by one. After enough glyphs for one side have been shown, everything is rotated by -90 degrees before continuing with the remaining glyphs.

To know when enough glyphs have been shown on the side, we increment a counter by 4 each time a glyph is shown. If the counter value modulo the string length is less than 4, then we know we have to rotate:

char  counter  mod 6  compared to 4
 h       4       4          =
 e       8       2          <   => rotate
 l      12       0          <   => rotate
 l      16       4          =
 o      20       2          <   => rotate
 !      24       0          <   => rotate

enter image description here

Commented and un-golfed source code:

0                      % n
{%kshow                % n char1 char2
  = =                  % n
  4 add dup            % n' n'
  t length mod         % n' (n' mod t_length)
  4 lt                 % n' bool
  {-90 rotate}if       % n'
}                      % n kshowProc
% First 0 for moveto. We add it here to take 
% advantage of the surrounding self delimiting tokens.
0                      % n kshowProc 0
% We change the graphics state so that the drawn
% text is at a nice size and not off screen.
[0 3 -3 0 9 9]concat   % n kshowProc 0
0                      % n kshowProc 0 0
moveto                 % n kshowProc
/Courier 5 selectfont  % n kshowProc
t                      % n kshowProc text
kshow                  % n

Python 3(120)

for i in range(1,h):p(s[n-i]+' '*q+s[q+1+i])





z            o
y            p
x            q
w            r
v            s
u            t
t            u
s            v
r            w
q            x
p            y
o            z

05AB1E, 19 17 bytes


Port of my Charcoal answer.

Try it online.


g            # Get the length of the (implicit) input-string
 4/          # Divide it by 4
   D         # Duplicate it
    î        # Ceil the copy
     sï      # Swap, and floor the other one
       ‚     # Pair the two together
        >    # Increase both by 1
         4∍  # And extend it to size 4
I            # Push the input-string
Ž9¦          # Push compressed integer 2460
   S         # And convert it to a digit-list: [2,4,6,0]
Λ            # Use the Canvas builtin with these three arguments
             # (which is implicitly output immediately as result)

See this 05AB1E tip of mine (section How to compress large integers?) to understand why Ž9¦ is 2460.

The Canvas builtin takes three arguments:

  1. The length of the lines. For this we use the list of four values we created at the start: \$\left[ \left\lceil\frac{L}{4}\right\rceil+1, \left\lfloor\frac{L}{4}\right\rfloor+1, \left\lceil\frac{L}{4}\right\rceil+1, \left\lfloor\frac{L}{4}\right\rfloor+1 \right]\$.
  2. The characters we want to display, which is the input-string.
  3. The directions in which to draw, which is [2,4,6,0]. These directions map to [→,↓,←,↑].

For a more detailed explanation of the Canvas builtin, see this 05AB1E tip of mine.


Python 2.x: 137

I'm new to code golfing and quite sure this can be improved…

def s(t):c=len(t);w=1+c/4;h=(c-w-w)/2;u=w+h;n='\n';print t[:w]+n+n.join(map(((w-2)*' ').join,zip(t[:w+u-1:-1],t[w:u])))+n+t[w+u-1:u-1:-1]

Visual testing code:

from itertools import chain
from string import letters
for i in range(8,101,2):
    t = ''.join(chain(letters))[:i]
    print '%d: %s' % (i, t)
    print '-----'

Something of interest: This solution depends on integer math. If you just do the math symbolically, you'll find that h=(c-w-w)/2 => h=w-2, but if you substitute that result every other result will be missing two lower-left characters.


K, 84

{-1'(*r;((|r 3),\:(w-2)#" "),'r 1;|(r:(0,+\(w;h;w;h:_(l-2*w:-_-(1+(l:#x)%4))%2))_x)2);}


k){-1'(*r;((|r 3),\:(w-2)#" "),'r 1;|(r:(0,+\(w;h;w;h:_(l-2*w:-_-(1+(l:#x)%4))%2))_x)2);}"HelloWorld"
d  o

k){-1'(*r;((|r 3),\:(w-2)#" "),'r 1;|(r:(0,+\(w;h;w;h:_(l-2*w:-_-(1+(l:#x)%4))%2))_x)2);}"Hellooooooooooooooo Worlddddd!"
!       o
d       o
d       o
d       o
d       o
d       o
lroW oooo

Scala (135)

The following snippet assumes that x contains the string to format, and should be pasted in the scala REPL:

val (h,w)=((x.size+3)/4,println(_:Any));val s=x.grouped(h)toSeq;w(s(0));for((l,r)<-s(1)zip(s(3)reverse))w(r+" "*(h-2)+l);w(s(2)reverse)

If you don't have scala installed, you can quickly check it using this online Scala interpreter: http://www.simplyscala.com/. Just paste the following text end press evaluate:

val x="HelloWorld"
val (h,w)=((x.size+3)/4,println(_:Any));val s=x.grouped(h)toSeq;w(s(0));for((l,r)<-s(1)zip(s(3)reverse))w(r+" "*(h-2)+l);w(s(2)reverse)

Charcoal, 16 12 bytes


-4 bytes thanks to @Neil.

Try it online (verbose) or try it online (pure).


Draw a box using the characters in the implicit input-string:

Box(..., ..., q);

With a width \$\left\lceil\frac{L}{4}\right\rceil+1\$ (where \$L\$ is the length of the input), by splitting the input-string into parts of size 4 and getting this list's length incremented by 1:


And height \$\left\lfloor\frac{L}{4}\right\rfloor+1\$:

  • 1
    \$\begingroup\$ I've come up with two 14-byte variations: SθB⊕L⪪θ⁴⊕⊘⊘Lθθ and Sθ≔⊕⊘⊘LθηB⌈ηηθ. Also strictly speaking the Sθ is unnecessary. \$\endgroup\$
    – Neil
    Commented Nov 18, 2020 at 14:45
  • \$\begingroup\$ @Neil Thanks! Can't believe I forgot about q being implicitly filled with an input-string and only the input-integer being mandatory. And thanks for the additional -2. Nice alternative as well! :) \$\endgroup\$ Commented Nov 18, 2020 at 15:23
  • \$\begingroup\$ Your verbose explanation doesn't match your verbose link. \$\endgroup\$
    – Neil
    Commented Nov 18, 2020 at 15:45
  • \$\begingroup\$ @Neil Ah, you're indeed correct. Should be fixed now. \$\endgroup\$ Commented Nov 18, 2020 at 15:51

PHP (149)

The text to print should be in a variable named $x.

';while($i--)echo$x[$l+$i].str_repeat(' ',$w-2).$x[$h-$i-1].'

JAVA - 320

public class A{
public static void main(String[] a){
String s=a[0];
int l=s.length(),h=l/2,f=h-1,i=0;       
System.out.print(" ");

Note : - Input is taken from command line

Input : - HelloWorld

Output : -

d  o

Input : - abcdefghijklmnopqrstuvwxyz

Output : -

z          m
  • \$\begingroup\$ Please read the rules more carefully, especially nr. 3. \$\endgroup\$
    – vsz
    Commented Jan 24, 2013 at 9:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.