# Crate art stacking

Your task is, given a array of numbers, that is strictly increasing, output the crate stack. The input is an array of positive integers which represents which layer has how many crates there are. So the first number is the top layer and so on. The sum of the array is the size of the crate.

Since the array order follows this rule layer 1>layer 2>layer 3..., we have to make sure every layer above the bottom one is centered with respect to the whole width of the layer below it. If it can't be centered, place it so that it's as close as possible to the center (you can choose it to be shifted left or right).

## Testcases

[1]
->
*

[1,2]
->
***
* *
***
******
* ** *
******

[2,3]
->
**********
*   **   *
*   **   *
*   **   *
**********
***************
*   **   **   *
*   **   **   *
*   **   **   *
***************

[2,3,4]
->
******************
*       **       *
*       **       *
*       **       *
*       **       *
*       **       *
*       **       *
*       **       *
******************
***************************
*       **       **       *
*       **       **       *
*       **       **       *
*       **       **       *
*       **       **       *
*       **       **       *
*       **       **       *
***************************
************************************
*       **       **       **       *
*       **       **       **       *
*       **       **       **       *
*       **       **       **       *
*       **       **       **       *
*       **       **       **       *
*       **       **       **       *
************************************


Leading spaces and trailing spaces are allowed

This is , so shortest code wins!

• Is * as character mandatory, or could we use any single non-whitespace character? Mar 4, 2022 at 8:27
• I think you should add at least one test case with increasing steps other than 1, such as [1,3]. Mar 4, 2022 at 21:00
• I assumed that you meant inputs incrementing by one based on your test cases. Is this true?
– code
Mar 4, 2022 at 21:22

# JavaScript, 225 219 bytes

-7 thanks to Arnauld's suggestion

s=d=>{j=console.log;o=(p,g)=>p.repeat(g);a="*";[t]=d.slice(-1);if(t==1)return j(a);b=t*-~t/2-2;b=b<1?1:b;d.map(i=>{h=o(" ",(t*b-i*b)/2);c=${h+o(o(a,b+2),i)}${o(
${h+o(*${o(" ",b)}*,i)},b)}
${h+o(o(a,b+2),i)};j(c)})}  Try it online! Unminified for your enjoyment: function stack(arr) { String.prototype.o = function(p) { return this.repeat(p); } const a = "*"; const [t] = arr.slice(-1); if(t == 1) return console.log(a); let sum = ((t * t + t) / 2) - 2; if(sum < 1) sum = 1; arr.forEach(i => { const spaces = " ".o((t * sum - i * sum) / 2); const crate = ${spaces + a.o(sum + 2).o(i)}${\n${spaces + *${" ".o(sum)}*.o(i)}.o(sum)}\n${spaces + a.o(sum + 2).o(i)};
console.log(crate);
});
}

• It seems like your code doesn't center the crates properly (try with [1, 3] for instance). Mar 4, 2022 at 8:32
• Some tips. 1) Because your function is not recursive, you don't have to put s= in your main code (you can put it the header section of TIO). 2) You should also put s([2, 3, 4]); in the footer section of TIO so that the correct size is reported. 3) ((t*t+t)/2)-2 can be simplified to t*-~t/2-2 and (t*b-i*b)/2 to (t-i)*b/2. 4) You can use literal linefeeds instead of \n's. Mar 4, 2022 at 17:42
• @ophact the question states the input must be "strictly increasing" (based on the examples, by 1), so that input is invalid.
– code
Mar 4, 2022 at 20:42
• @Arnauld Thanks for your feedback. Does \n count as one or two bytes?
– code
Mar 4, 2022 at 20:49
• What should be counted is the actual number of bytes in the source code. So \n is two bytes. Mar 4, 2022 at 20:57

# Python 3.8 (pre-release), 128 bytes

lambda n:(s:=sum(n))and'\n'.join('\n'.join((n[-1]-N)*s//2*' '+N*('*'+'* '[0<m<s-1]*(s-2)+'*'*(s>1))for m in range(s))for N in n)


Try it online!

# 05AB1E, 21 bytes

O'*Ž9¦.Λ¶¡¸Iи€øJ€»».c


Explanation:

O              # Sum the (implicit) input-list
'*           '# Push "*"
Ž9¦         # Push compressed 2460
.Λ       # Use the (modifiable) Canvas builtin with these three options
¶¡             # Split this box by newlines
¸            # Wrap it in a list
Iи          # Repeat it each of the inputs amount of times
€         # Map over each list of boxes:
ø        #  Zip/transpose; swapping rows/columns
J       # Join each inner row together to a single string
€»     # Join all inner lines by newlines
»    # Join each vertical line of boxes by newlines
.c  # Centralize all lines
# (after which the result is output implicitly)


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

As for some additional information about the modifiable Canvas builtin .Λ:
It takes 3 arguments to draw an ASCII shape:

1. Length of the lines we want to draw
2. Character/string to draw
3. The direction to draw in, where each digit represents a certain direction:
7   0   1
↖ ↑ ↗
6 ← X → 2
↙ ↓ ↘
5   4   3


O'*Ž9¦ creates the following Canvas arguments:

1. Length: the sum of the input (e.g. for [2,3,4] this would be 9)
2. Character: "*"
3. Directions: [2,4,6,0], which translates to $$\[→,↓,←,↑]\$$

Try just the Canvas portion online.

Step 1: Draw 9 characters ("*********") in direction 2/→:

*********


Step 2: Draw 9-1 characters ("********") in direction 4/↓:

*********
*
*
*
*
*
*
*
*


Step 3: Draw 9-1 characters ("********") in direction 6/←:

*********
*
*
*
*
*
*
*
*********


Step 4: Draw 9-1 characters ("********") in direction 0/↑:

*********
*       *
*       *
*       *
*       *
*       *
*       *
*       *
*********


After which we can use this string since we're using the modifiable Canvas builtin .Λ, instead of the Canvas builtin Λ that would output directly.

See this 05AB1E tip of mine for an in-depth explanation of the Canvas builtin.

# Charcoal, 29 bytes

ＦＬθ«Ｊ⊘×§θιΣθ×ιΣθＦ§θι«ＢΣθ*ＭΣθ←


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

ＦＬθ«


Loop over each layer.

Ｊ⊘×§θιΣθ×ιΣθ


Jump to the top left corner of the last box in that layer.

Ｆ§θι«


Loop over each box in the layer.

ＢΣθ*


Draw the box of the appropriate size.

ＭΣθ←


Move to the previous box.

# JavaScript (ES6),  132 128 120  119 bytes

Non-centered crates are shifted to the right.

f=(a,x=W=a.every(n=>w+=N=n,w=y=0)+w*N)=>(q=W-a[y/w|0]*w)? *
[--x?(X=x+q/2)%w<2|-~y%w<2&&X>=q&X<W:++y&&2]+f(a,x||W):''


Try it online!

### Commented

f = (                  // f is a recursive function taking:
a,                   //   a[] = input array
// and also using:
x =                  //   (x, y) = current position
W =                  //   W = total row width, w = crate width
a.every(n =>       //   for each value n in a[]:
w += N = n,      //     add n to w and save n in the global scope
w = y = 0        //     start with w = 0 and y = 0
)                  //   end of every(), which returns 1
+ w * N            //   add the last value multiplied by w
) =>                   //
( q = W -              // define q as the total row width less the
a[y / w | 0] * w // total width of the crates on this row
) ?                    // if q is not NaN:
 *\n[              //   character lookup:
--x ?              //     decrement x; if it's not 0:
(X = x + q / 2)  //       define X as x + q / 2
% w < 2 |        //       if we're over a vertical crate edge
-~y % w < 2      //       or over a horizontal crate edge
&&               //       and
X >= q & X < W   //       we're over the crates in this row,
//       then put a '*', else put a space
:                  //     else:
++y && 2         //       increment y and put a linefeed
] +                  //   end of character lookup
f(a,                 //   append the result of a recursive call
x || W)         //   make sure to restart with x = W if x = 0
:                      // else:
''                   //   stop the recursion


# Vyxal, 19 bytes

∑×2460ø^↵vẋƛ∩Ṡ;føĊ⁋


Try it Online!