Star pyramid

Easy TimeO(n²) SpaceO(n²)

Given a row count n, return a centred pyramid of stars as an array of n strings. Row i holds 2i − 1 stars, so the counts run 1, 3, 5 and stay odd, and it carries n − i spaces in front of them. There is no padding after the stars, so every row ends on a *.

Examples

Example 1

Input
n = 5
Output
    *
   ***
  *****
 *******
*********
[" *"," ***"," *****"," *******","*********"]
Five rows: 1, 3, 5, 7 and 9 stars behind 4, 3, 2, 1 and 0 spaces.

Example 2

Input
n = 3
Output
  *
 ***
*****
[" *"," ***","*****"]
The last row of a three-row pyramid has no padding left and 2 × 3 − 1 = 5 stars.

The Code

function pyramid(n) {
  const rows = [];
  for (let row = 1; row <= n; row++) {
    let line = "";
    for (let space = 1; space <= n - row; space++) {
      line += " ";
    }
    for (let star = 1; star <= row * 2 - 1; star++) {
      line += "*";
    }
    rows.push(line);
  }
  return rows;
}
pyramid(5);
Done

The first 16 calls, of 51. This one does not fit on a page.

Step through pyramid(5) call by call

Explanation

Two counts move per row, against each other: a row gains two stars as it gives up one space. The star added on the left takes the place the padding gave up, which is what holds the tip in one column. Each space is drawn as · in the rows below.

  1. 1

    row is 1. The first inner loop runs while space is at most n - row, so four spaces go onto line; the second runs while star is at most row * 2 - 1, so one star follows them. Only then is line pushed.

    ····*
    0

    n - row=4row * 2 - 1=1

    rows.push("····*")

  2. 2

    row is 2. n - row has dropped to 3 while row * 2 - 1 has risen to 3, so the row gives up a space and takes two stars — one on each side of the star already there.

    ····*
    0
    ···***
    1

    n - row=3row * 2 - 1=3

    rows.push("···***")

  3. 3

    row is 3: two spaces and five stars. The two counts always move together, one down by one and the other up by two, which is why the left edge slopes by a single column a row.

    ····*
    0
    ···***
    1
    ··*****
    2

    n - row=2row * 2 - 1=5

    rows.push("··*****")

  4. 4

    row is 4: one space and seven stars.

    ····*
    0
    ···***
    1
    ··*****
    2
    ·*******
    3

    n - row=1row * 2 - 1=7

    rows.push("·*******")

  5. 5

    row is 5, so n - row is 0 and the first inner loop does not run at all. The second appends 5 * 2 - 1 = 9 stars, and the outer loop ends with rows five strings long.

    ····*
    0
    ···***
    1
    ··*****
    2
    ·*******
    3
    *********
    4

    n - row=0row * 2 - 1=9

    return rows → 5 rows