Build a Tower
Tags: kata, challenge, codewars, javascript
Published: 2019-12-02 18:07:28

## Task description

> Build a tower given an argument representing the number of floors.
> 
> A tower block is represented as *
> 
> For example, a tower of 3 floors looks like below
> 
> [
  '  *  ', 
  ' *** ', 
  '*****'
]
> and a tower of 6 floors looks like below
> 
> [
  '     *     ', 
  '    ***    ', 
  '   *****   ', 
  '  *******  ', 
  ' ********* ', 
  '***********'
]

## Task solution

### Tests

```javascript
describe("tower builder", () => {
  it("Throws when invalid input is provided", () => {
    expect(() => towerBuilder("1")).toThrow(/InvalidArgumentException/);
    expect(() => towerBuilder(1, 1)).toThrow(/InvalidArgumentException/);
    expect(() => towerBuilder(1, "**", " ", "1")).toThrow(/InvalidArgumentException/);
    expect(() => towerBuilder(1, "*", 1)).toThrow(/InvalidArgumentException/);
    expect(() => towerBuilder(1, "*", "  ")).toThrow(/InvalidArgumentException/);
    expect(() => towerBuilder(1, "*", " ", "1")).toThrow(/InvalidArgumentException/);
    expect(() => towerBuilder(1, "*", " ", 1, {})).toThrow(/InvalidArgumentException/);
  });

  it("Should return valid towers", () => {
    expect(towerBuilder(1, "$")).toEqual(["$"]);
    expect(towerBuilder(2, "$", "-", 2)).toEqual(["$$$"]);
    expect(towerBuilder(2, "$", "-", 1, ["test"])).toEqual(["test", "-$-", "$$$"]);
    expect(towerBuilder(3, "+", ">")).toEqual([">>+>>", ">+++>", "+++++"]);
    expect(towerBuilder(10)).toEqual(["         *         ", "        ***        ", "       *****       ", "      *******      ", "     *********     ", "    ***********    ", "   *************   ", "  ***************  ", " ***************** ", "*******************"]);
  });
});
```

Beginning with the usual input validation cases, we then test our towers themselves, in the examples above you can see our Jest tests building towers of varying sizes and using different symbols to affect the appearance of the tower.

### Implementation

For the implementation I knew I would use recursion from the second I read the challenge description since this is just a repetitive task which generates the same output on each iteration just at a different size for each item output. The implementation I ended up with looks like so:

```javascript
function towerBuilderRecursive(
  nFloors,
  brickCharacter = "*",
  spacer = " ",
  currentIndex = 1,
  items = []
) {
  if (!Number.isInteger(nFloors)) {
    throw new Error(`InvalidArgumentException: Parameter 1 must be an integer. Received: ${typeof nFloors}`);
  } else if(typeof brickCharacter !== "string" || brickCharacter.length !== 1) {
    throw new Error(`InvalidArgumentException: Parameter 2 must be a string of length 1. Received: ${typeof brickCharacter} ${typeof brickCharacter === "string" && `with length ${brickCharacter.length}`}`);
  } else if(typeof spacer !== "string" || spacer.length !== 1) {
    throw new Error(`InvalidArgumentException: Parameter 3 must be a string of length 1. Received: ${typeof spacer} ${typeof spacer === "string" && `with length ${spacer.length}`}`);
  } else if (!Number.isInteger(currentIndex)) {
    throw new Error(`InvalidArgumentException: Parameter 4 must be an integer. Received: ${typeof currentIndex}`);
  } else if (!Array.isArray(items)) {
    throw new Error(`InvalidArgumentException: Parameter 5 must be an array. Received: ${typeof items}`);
  }

  const space = spacer.repeat(nFloors - currentIndex);
  const brick = brickCharacter.repeat((2 * currentIndex) - 1);
  items.push(`${space}${brick}${space}`);
  return currentIndex === nFloors ? items : towerBuilderRecursive(
    nFloors, 
    brickCharacter, 
    spacer, 
    currentIndex + 1, 
    items
  );
}
```

We begin with our checks as usual to cover the test cases where we expect failure. From there we begin building the parts of our tower, namely, the `space` and the `brick` variables. The space is basically what we want to put on the left and right of the `brick`s and the `brick` itself is the body component the tower itself.

Imagine the following pseudo code:

```text
floors = 3
brick = "+"
spacer = "-"
towerBuilderRecursive(floors, brick, spacer)
 -> first call
  -> currentIndex = 1
  -> space = spacer * (floors - currentIndex) = "--"
  -> brick = brick * (2 * currentIndex) - 1 = "+"
  -> items = ["--+--"]
 -> second call
  -> currentIndex = 2
  -> space = spacer * (floors - currentIndex) = "-"
  -> brick = brick * (2 * currentIndex) - 1 = "+++"
  -> items = ["--+--", "-+++-"]
 -> third call
  -> currentIndex = 3
  -> space = spacer * (floors - currentIndex) = ""
  -> brick = brick * (2 * currentIndex) - 1 = "+++++"
  -> items = ["--+--", "-+++-", "+++++"]
  -> currentIndex === floors -> return items
returns -> [
"--+--",
"-+++-",
"+++++"
]
```

## Conclusions

I always like to use recursion when I can and this was the perfect challenge to use it with. Overall the challenge itself was realtively simple once the algorithm was worked out and the math simplified down to what it is now. Thanks for reading and see you in the next one!