# I Got 99 Problems, and Pyramid’s Just One

--

Hello, fellow soon-to-be software developer. If you are preparing for upcoming interviews like me, you’re most likely (or will about to be) grinding away on loads of algorithm problems. In this post, I’d like to share a walkthrough of a problem I recently solved, in hope of better understanding it myself, as well as helping anyone who might be struggling with similar problems.

For this particular bad boy, we’re tasked with writing a function that prints out a two-sided pyramid of `n` levels that follows a couple of simple rules. I figured out two ways of tackling this (one I much prefer over the other). Let’s jump in!

## Two-Sided Pyramid, Explained

Specific instruction for this problem is as follows:

Write a function that accepts a positive number n. The function should console log a pyramid shape with n levels using the # character. Make sure the pyramid has spaces on both the left *and* the right-hand sides.

Examples:

Side note: This problem was taken from Stephen Grider’s Udemy course on Algorithms + Data Structures, which I highly recommend.

## Solution #1

I first looked at the examples given to identify common patterns shared and jotted down these observations. Here is how I broke down the patterns using `pyramid(4)` as a case example.

• First, I related my observations to the stable argument `n`. The pyramid consists in this case of `4` or `n` rows.
• Next, I went row-by-row, and again wrote down my observations regarding how many spaces are on either sides of the `#`. From this, I deduced that `spaceCount` or the number of spaces on either side starts at `n — 1` (or `4 — 1`, which is `3`). For each new row, `spaceCount` decreases by `1` on either side, until you reach the final row, in which case the final `spaceCount` is `0`.
• On the other hand, the `hashCount` or number of `#`’s in the middle of each row, starts at `1` and increments by `2` each time you move onto a new row.
• With these observations in mind, I started pseudo-coding out the solution, which looks like this:
1. Create a variable called `spaceCount` initially set to `n — 1`.
2. Create another variable called `hashCount` initially set to `1`.
3. While `spaceCount` hasn’t reached below`0`, `console.log` out `spaceCount` number of spaces, followed by `hashCount` number of `#`’s, followed again by `spaceCount` number of spaces. I used `spaceCount` as the variable whose value determines when I will be “done”, as I know that we will have finished printing the pyramid once we reach the row with only `#`'s and no spaces.
4. After each iteration, we set the new `spaceCount` to be one less than what it was, and we set the new `hashCount` to be two more than what it was.
• Then I coded out my solution:

Within my outer while loop, I created two variables, called `spaces` and `hashes` which will store the actual string fragments; initially they are empty strings. I created two inner while loops that add to said empty strings either spaces or `#`'s according to the current `spaceCount` and `hashCount`. Next, I concatenated the string parts and `console.log`’ed them out. And lastly, I decrement `spaceCount` by `1` and increment `hashCount` by `2` for each iteration of the outer while loop.

And voila, completed! I like this first solution as it followed exactly what I observed without much math (beyond counting) involved. The next solution is a bit complicated, in my opinion, but I find that learning multiple ways to solve the same problem always ends up teaching me something new.

## Solution #2

This solution involves seeing the pyramid in terms of rows and columns. This way, you can identify each position in the pyramid by specifying the row number it belongs to and the column number it belongs to in a battleship-esque way. Using this matrix, we can determine at which position to add `#` and at which to add space. I drew out a diagram, labeled `rowIdx`’s and `columnIdx`’s and identified some observations:

There are some “stable” variables we can take note of here. First is that all rows share a common “midpoint” at `columnIdx 3`, we can use this to figure out the “range” of `columnIdx`’s where we will be adding `#`'s rather than spaces. Second, we notice that the length of each row is consistently `7`. This is useful to know so that when we are constructing out each row, we know when to stop.

We will make use of two `for` loops: an inner loop that adds either `#` or a space to a particular row, and an outer loop that will print out each row. Let’s solve this one layer at a time, by first constructing the outer loop:

• In line two, we specify that we will be creating rows from index `0` to the index right before `n`. Given the 0-based indexing that is happening here, the condition `rowIdx < n` will make sure that we end the loop with `n` number of rows printed out. `rowIdx++` is the iteration part of the `for` loop, which ensures that we increment the index by one with each iteration.
• Notice here that `row` has not yet been defined. Next, let’s talk through the logic regarding how we will flesh out each row given the observations we made, and then code accordingly.

First I wrote out how to calculate the stable length of each row from `n` since `n` is the only argument passed into the function; hence, we need to find ways to deduce everything else in relation to `n`. To get from `n = 4` to `rowLength = 7`, we can use the formula: `rowLength = n * 2 — 1`. Knowing the length is useful for our inner `for` loop, as we can set it as the condition, where as long the `columnIdx` is less than the `rowLength`, we can continue adding characters (either `#` or space).

Next, I wrote out how I can calculate the `midpoint`, in the case above, it is at `columnIdx 3`. And this is the formula: `midpoint = Math.floor(rowLength / 2)`. Since `rowLength` in this case is `7`, `7 / 2 = 3.5`. Using `Math.floor()`, we round the result down to `3`, hence arriving at `columnIdx 3`.

Next, I deduced the pattern of spaces and `#`'s for each row in relation to the `midpoint` and `rowIdx`, like so:

• Looking at the pattern above, we can say that the `columnIdx`’s where we will be adding `#`'s are from the `startIdx` of `midpoint — rowIdx` to the `endIdx` of `midpoint + rowIdx`. Refer to the drawn diagram above for a visual of the row and column matrix.

Given all this information, we can write the logic to construct each row as follows:

1. Create a variable called `row` that is initially an empty string
2. Define `rowLength`
3. Define `midpoint`
4. Loop from `columnIdx` to the index just before `rowLength`
5. The range of indices where we are to place the `#`'s are from `startIdx` of `midpoint — rowIdx` to the `endIdx` of `midpoint + rowIdx`, as stated above
6. If the current `columnIdx` belongs in that range, then add a `#` to the `row` string, if not, add a space instead

And finally, the code:

Again, I prefer the first solution, as it involves less calculation and is much more straightforward. However, this solution allows for a different view of the same problem. There is a third solution that involves recursion, but I won’t be going into that here.

Skills I practiced from solving this problem include: 1) articulating in human terms step-by-step the patterns I observed in the examples given and 2) relating said observations back to the “stable” variables, especially the argument(s) provided to the function.

I hope you find this helpful. And I wish you the best on your next coding interview!

--

--