# Draw Growing Stacks of Boxes

In this challenge, your task is to draw an ASCII art representation of several stacks of boxes of increasing height. You are given as input the number of stacks, which is a positive integer. The first stack contains one box of size 2x2. The second stack contains 2 boxes of size 3x3. In general, the kth stack contains k boxes of size (k+1)x(k+1).

The borders of each box are drawn using the characters -|+, and their interior consists of whitespace. Adjacent boxes share their borders, and corners should always be drawn with +, even when they are part of a border of another box.

# Examples

Output for 1:

++
++


Output for 2:

 +-+
| |
+-+
++ |
++-+


Output for 3:

   +--+
|  |
|  |
+--+
|  |
+-+  |
| +--+
+-+  |
++ |  |
++-+--+


Output for 5:

          +----+
|    |
|    |
|    |
|    |
+----+
|    |
|    |
|    |
+---+    |
|   +----+
|   |    |
|   |    |
+---+    |
|   |    |
|   +----+
+--+   |    |
|  +---+    |
|  |   |    |
+--+   |    |
|  |   +----+
+-+  +---+    |
| +--+   |    |
+-+  |   |    |
++ |  |   |    |
++-+--+---+----+


# Rules and Scoring

The input can be received from STDIN, as a command line argument, or as a function argument. Output must go to STDOUT or closest equivalent. Any finite amount of trailing whitespace is allowed, as are preceding and trailing newlines, but there cannot be any extra preceding spaces.

This is code-golf, so the lowest byte count wins. Standard loopholes are disallowed.

• I think this ascii output is a good illustration for how n and n-1 are relatively prime. Two pluses will never overlap. Jun 24, 2015 at 18:36
• Is there any maximum limit for the input number? Jun 24, 2015 at 19:01
• @ThomasWeller Only the maximum limit of your language's native integer type. Jun 24, 2015 at 20:07
• It seems that this is quite a limiting factor. Some of the submissions will not work for Integer.MaxValue as input. Jun 24, 2015 at 22:15
• @ThomasWeller Oh, you're right of course... it was not my intention to invalidate existing answers. Let's overrule that: a solution should work for all inputs for which the total number of required characters in the output does not exceed Integer.MaxValue or equivalent. Jun 25, 2015 at 6:43

# CJam, 64 60 58 bytes

]ri:X{'|'}{I))*\I**XX*)Se[s}:L~:M.e>S'-LaI*~M}fI]zN*'}/'+*


Constructing each column at a time.

Try it online here

# Java (407 349 chars)

A few chars thanks to @Zgarb and @Geobits

Code

void s(int q){int d,h,y,i,j,x,z,t=q*q+1;char b;for(i=0;i<t;i++){z=x=0;d=t-i;for(j=0;j<(q*q+q)/2+1;j++){b=' ';h=x*x+1;if(x==z){y=x+1;if((d<=h&d%(x==0?1:x)==(x==1?0:1))|(y<=q&d<=y*y+1&d%(y==0?1:y)==(y==1?0:1)))b='+';else if(d<=h|y<=q&d<=y*y+1)b='|';x++;z=1;}else{if(d<=h&d%(x==0?1:x)==(x==1?0:1))b='-';z++;}System.out.print(b);}System.out.println();}}


Not sure if this is optimal, but it's my first attempt, I will probably try to put it in a better golfing language later. Any suggestions are welcome!

Expanded

class StackingBlocks{
public static void main(String[]a){
int d,h,y,i,j,x,z,t,q=10;
t=q*q+1;
char b;
for(i=0;i<t;i++){
z=x=0;
d=t-i;
for(j=0;j<(q*q+q)/2+1;j++){
b=' ';
h=x*x+1;
if(x==z){
y=x+1;
if((d<=h&d%(x==0?1:x)==(x==1?0:1))|(y<=q&d<=y*y+1&d%(y==0?1:y)==(y==1?0:1)))
b='+';
else if(d<=h|y<=q&d<=y*y+1)
b='|';
x++;
z=1;
}else{
if(d<=h&d%(x==0?1:x)==(x==1?0:1))
b='-';
z++;
}
System.out.print(b);
}
System.out.println();
}
}
}


Check it out here.

• Quick tips for 10 bytes: 1) Replace && and || with & and |. 2) Move int declarations into the for (for(int i=0,j,x,z;...). 3) You have one too many braces at the end of your golfed function. Jun 24, 2015 at 17:50
• You have a lot of comparisons of the form a+1<=b+1; they can be replaced by a<=b. Jun 24, 2015 at 17:51
• q*q+1 should probably just be assigned to another variable. You use it 9 times or so, and you could save a bunch by saying a=q*q+1 once. Also, q*(q+1) is just q*q+q. Jun 24, 2015 at 18:04
• I was just doing that Geobits and Zgarb, thanks for the suggestions!
– cmxu
Jun 24, 2015 at 18:06
• You could look for a recursive solution, maybe? It looks like there should be a nice one. Jun 24, 2015 at 18:50

# Python 2, 144 128 bytes

n=input()
i=n*n
while-~i:j=x=1;l="";exec'y=i%j<1;z=i>j*j;l+=j*z*" "or"|+"[x|y]+" -"[y]*~-j;x=y^z>z;j+=1;'*n;print l+"|+"[x];i-=1


Bit twiddling. Bit twiddling everywhere.

# Python, 188 bytes

Mathematically calculates the character at each x,y position. It was tricky making the +s print on both sides of each box as well as stopping the rightmost +s of what would be n+1th boxes.

n=input();l=1;c=0
for y in range(n*n,-1,-1):
s=""
for x in range((n*n+n)/2+1):k=((8*x+1)**.5+1)/2;i=int(k);b=y<=i**2;s+=" |-+"[((k==i)+2*((y%l+c)*(y%i+(k==n+1))<1))*b];l=i;c=b^1
print s

• what does (8*x+1)**.5+1 do ? Jun 24, 2015 at 21:32
• @Agawa001 Looks like an inverse triangle function. Jun 24, 2015 at 21:36
• @Geobits Beat me to answering what my own code does!
– KSab
Jun 24, 2015 at 21:37
• @Geobits yea i was thinkin of something like floor$sqrt(2*n-sqrt(2*n))$ , Jun 24, 2015 at 21:39
• @ThomasWeller python will automatically convert that to a long which has no upper limit.
– KSab
Jun 24, 2015 at 23:54

## C# - 304 bytes (function)

void b(int s){int h=s*s,w=h+s>>1,x,y,j;var c=new int[w+1,h+1];for(;s>0;s--){for(y=s*s-s;y>=0;y-=s){x=s*s-s>>1;for(j=0;j<s;){c[x+j,y]=c[x+j,y+s]=13;c[x,y+j]=c[x+s,y+j++]=92;}c[x,y]=c[x+s,y]=c[x+s,y+s]=c[x,y+s]=11;}}for(y=h;y>=0;y--){for(x=0;x<=w;x++)Console.Write((char)(32+c[x,y]));Console.WriteLine();}}


or 363 bytes (full code)

namespace System{class C{static void Main(string[]a){int s=int.Parse(a[0]),h=s*s,w=h+s>>1,x,y,j;var c=new int[w+1,h+1];for(;s>0;s--){for(y=s*s-s;y>=0;y-=s){x=s*s-s>>1;for(j=0;j<s;){c[x+j,y]=c[x+j,y+s]=13;c[x,y+j]=c[x+s,y+j++]=92;}c[x,y]=c[x+s,y]=c[x+s,y+s]=c[x,y+s]=11;}}for(y=h;y>=0;y--){for(x=0;x<=w;x++)Console.Write((char)(32+c[x,y]));Console.WriteLine();}}}}


I tried to avoid if statements. Ungolfed:

namespace N
{
public class Explained
{
static void boxes(string[] args)
{
int size = int.Parse(args[0]);
int height = size * size + 1;
int width = size * (size + 1) / 2 + 1;
var canvas = new int[width, height];
for (; size > 0; size--)
drawboxes(size, canvas);

for (int y = height - 1; y >= 0; y--)
{
for (int x = 0; x < width; x++)
Console.Write((char)(32 + canvas[x, y]));
Console.WriteLine();
}
}

static void drawboxes(int size, int[,] canvas)
{
int x = size * (size - 1) / 2;
for (int i = size - 1; i >= 0; i--)
{
drawbox(x, i * size, size, canvas);
}
}

static void drawbox(int x, int y, int size, int[,] canvas)
{
for (int i = 0; i < size; i++)
{
canvas[x + i, y] = 13; // +32 = '-'
canvas[x + i, y + size] = 13;
canvas[x, y + i] = 92; // +32 = '|'
canvas[x + size, y + i] = 92;
}
canvas[x, y] = 11; // +32 = '+'
canvas[x + size, y] = 11;
canvas[x + size, y + size] = 11;
canvas[x, y + size] = 11;
}
}
}

• My solution does not work for any input of Integer range as defined by OP. I'd need to use long instead. Jun 24, 2015 at 22:12

# Ruby (205 bytes)

Takes the number as a command line arguments. It starts with a fail leading newlines, but that's allowed.

n=\$*[0].to_i
m=n+1
f=m.times.inject(:+)+1
c=((" "*f+p=?+)*n*m).split p
y=0
1.upto(n){|b|(b*b+1).times{|x|d=x%b==0;r=c[x]
d&&b.times{|g|r[y+g]=?-}
r[y]=d||r[y]==p ?p:?|
r[y+b]=d ?p:?|}
y+=b}
puts c.reverse


# JavaScript (ES6), 293 bytes

(n,o='',r,f,t,u,b,c,e=n*n+1,i)=>{for(t=0;e>t;t++){for(c=b=0,d=e-t,u=0;(n*n+n)/2+1>u;u++)i=" ",r=b*b+1,b==c?(f=b+1,d<=r&d%(0==b?1:b)==(1==b?0:1)|n>=f&d<=f*f+1&d%(0==f?1:f)==(1==f?0:1)?i="+":d<=r|n>=f&d<=f*f+1&&(i="|"),b++,c=1):(d<=r&d%(0==b?1:b)==(1==b?0:1)&&(i="-"),c++),o+=i;o+="\n"}return o}


I ran this in Firefox. Ignore the " the console adds between the strings. This is mostly ES5 stuff but I'll try to golf this more.

Ungolfed / ES5

function box(n, o, r, f, t, u, b, c, e, i) {
if (o === undefined) o = "";
if (e === undefined) e = n * n + 1;
return (function() {
for (t = 0; e > t; t++) {
for (c = b = 0, d = e - t, u = 0;
(n * n + n) / 2 + 1 > u; u++) i = " ", r = b * b + 1, b == c ? (f = b + 1, d <= r & d % (0 == b ? 1 : b) == (1 == b ? 0 : 1) | n >= f & d <= f * f + 1 & d % (0 == f ? 1 : f) == (1 == f ? 0 : 1) ? i = "+" : d <= r | n >= f & d <= f * f + 1 && (i = "|"), b++, c = 1) : (d <= r & d % (0 == b ? 1 : b) == (1 == b ? 0 : 1) && (i = "-"), c++), o += i;
o += "\n";
}
return o;
})();
}

document.getElementById('g').onclick = function(){ document.getElementById('o').innerHTML = box(+document.getElementById('v').value) };
<input id="v"><button id="g">Run</button><pre id="o"></pre>

# Python 2, 294 290

I got it working, but I still need to golf it more. I'm so happy, though, that was tough (for me, at least)!

I'll probably add an explanation later, unless it's immediately clear to someone...? I kind of doubt it.

Try it here

n=input()
w=n*n+n+2>>1
a=eval([[' ']*w]*-~n**2)
r=range
j=[i*i+i>>1for i in r(n+1)]
p=0
for i in r(w):
if i in j:
p+=p<n
for k in r(p*p+1):a[~k][i]='+'if k%p<1or' '<a[~k][i-1]<'.'else'|'
else:
for k in r(p*p+1):a[~k][i]=' 'if k%p else'-'
print'\n'.join(''.join(i)for i in a)


# Python - 243 bytes

Generates all the columns, replacing the overlaps on columns except the first one. Then it pads with spaces, transposes, and prints.

Q=input()
Y=[]
for i in range(Q):
f="+"+i*"-"+"+";x=map(list,zip(*([f]+["|"+" "*i+"|"]*i)*(i+1)+[f]))
if i:y=Y.pop();x[0][-len(y):]=y
Y+=x
print"\n".join("".join(i)for i in zip(*["".join(j[::-1]).ljust(Q*Q+1," ")for j in Y])[::-1])


I am considering translating to Pyth, but I will need a replacement for the pad function.