# Rectangle of text

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

Hell
d  o
lroW


Rules:

• 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.

### GolfScript, 565340 38 characters

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


You may test the script online.

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 |..| 00000032  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: The same code using ASCII tokens looks like this: t[0 9[t length 4 div dup ceiling 2 copy]{cvi{2 copy}repeat exch neg}forall]9 9 moveto/Courier 9 selectfont xyshow  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 xyshow  • +1 holy bajeezus. I'm seriously deficient in my knowledge of level-2 and beyond. – luser droog Jan 20 '13 at 6:51 • 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 ;-). – Thomas W. Jan 20 '13 at 7:22 • @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? – Thomas W. Jan 20 '13 at 10:51 • @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. – Howard Jan 24 '13 at 20:31 • @Howard: Argh!!! Can anyone ever beat GolfScript? – Thomas W. Jan 24 '13 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. l=x.size 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! • Nice! You can save two chars in the 5th line (remove spaces). – Thomas W. Jan 19 '13 at 21:00 • I like it. Thanks. Looks good that Ruby strings can be accessed like an array, I had to built one by myself. :) – memowe Jan 20 '13 at 14:16 • You could replace x.length with x.size (Saves 2 characters) – knut Jan 20 '13 at 22:22 • And 8 more using puts x[0..w=l/2-h=l/4]. – Howard Jan 24 '13 at 20:34 ## Perl (124118 109+3=112) This formerly was pretty straightforward. Counted all command line options as 1 character each. -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]  Example: $ 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]'
abcdefghijklmnopqrstuvwxyz
abcdefgh
z      i
y      j
x      k
w      l
v      m
utsrqpon

• 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 – amon Jan 20 '13 at 4:18 • Updated the code. – memowe Jan 20 '13 at 14:14 • 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). – amon Jan 20 '13 at 19:31
• Excellent golfification, @amon, would you edit it in my post please? That way the world can see who did it. :) – memowe Jan 20 '13 at 20:34

# Brainfuck - 194 187

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

• 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. – vsz Jan 20 '13 at 19:04
• 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. – captncraig Jan 22 '13 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},


Examples

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"]


• Hey, an array of strings? That's really bending the rules, isn't it? – Thomas W. Jan 20 '13 at 0:03
• @ThomasW. The comments in the answer indicate it's not a final solution. – kojiro Jan 20 '13 at 0:48
• Ah, I see! Wonder whether I should take the challenge and try something similar in PostScript... – Thomas W. Jan 20 '13 at 10:47
• I like how it looks now! – Thomas W. Jan 21 '13 at 19:30
• @Thomas W. Thanks. Getting the format to look right for a wide range of string lengths cost a lot of bytes. – DavidC Jan 21 '13 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. • 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? – Thomas W. Jan 21 '13 at 22:15 • @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. – amon Jan 22 '13 at 13:44 • 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' – Thomas W. Jan 22 '13 at 13:59

# PostScript (106)

This is inspired by dude's Mathematica solution.

0{= =
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


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 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)
s(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"
Hell
d  o
lroW

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!"
Hellooooo
!       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)


# Python 3(120)

s=input()
n=len(s)
h=n//4
q=(n+2)//4-1
p=print
p(s[:q+2])
for i in range(1,h):p(s[n-i]+' '*q+s[q+1+i])
p(s[n-h:q+h:-1])


## Test

### input:

abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz


### output:

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


## PHP (149)

The text to print should be in a variable named $x. @$s=substr;echo$s($x,-$w=($l=strlen($x)/2)-$h=$i=$l-2>>1).'
';while($i--)echo$x[$l+$i].str_repeat(' ',$w-2).$x[$h-$i-1].'
';echo$s(strrev($x),$l,$w);


# Python2.7 (99)

t=''.join(raw_input().split())
u=len(t)/2-1
print t[:u]+"\n"+t[-1]+" "*(u-2)+t[u]+"\n"+t[-2:u:-1]


Edit: It apparently violates the rule of encompassing maximum area inside.

# 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;
for(i=0;i<f;i++)
System.out.print(s.charAt(i));
System.out.print("\n"+s.charAt(l-1));
for(i=0;i<f-2;i++)
System.out.print(" ");
System.out.println(s.charAt(h-1));
for(i=l-2;i>h-1;i--)
System.out.print(s.charAt(i));}}


Note : - Input is taken from command line

Input : - HelloWorld

Output : -

Hell
d  o
lroW


Input : - abcdefghijklmnopqrstuvwxyz

Output : -

abcdefghijkl
z          m
yxwvutsrqpon

• Please read the rules more carefully, especially nr. 3. – vsz Jan 24 '13 at 9:14