CtCI - Triforce Secret Realm

CtCI - Triforce Secret Realm

Link has been sent to the Secret Realm to find the Triforce and save Hyrule. But the vile Ganondorf followed Link into the “Temple of Time”, trapped him, and took the Triforce for himself. The “Temple of Time” has been closed for a thousand years now, but the Sages finally found you and they need your help to open the Temple of Time’s door and join Link in the ultimate battle.

The Temple of Time’s surface contains several incrusted Triforces of different sizes, and the Sages believe that by creating Triforces of the corresponding sizes, the door will open. Even though no magic has worked until now, your programming skills will surely make the difference.

You must create a program that echoes a Triforce of a given size N.

  • A triforce is made of three identical triangles,
  • A triangle of size N should be made of N lines,
  • A triangle’s line starts from one symbol, and earns two symbols each line,
  • Take care, a dot must be located at the top/left to avoid automatic trimming.
.    @
    @@@
   @@@@@
  @     @
 @@@   @@@
@@@@@ @@@@@

For a Triforce with N=5:

.        @
        @@@
       @@@@@
      @@@@@@@
     @@@@@@@@@
    @         @
   @@@       @@@
  @@@@@     @@@@@
 @@@@@@@   @@@@@@@
@@@@@@@@@ @@@@@@@@@

We already have part of the solution given in the specifications of the problem. Each triangle is built with the same height as the input N and for each line we add two additional symbols starting with one in the first line.

var size int = 5

var spaces int
var line []byte
var count int = 1
var char = []byte("@")

for y := 1; y <= size; y++ {
    line = []byte{}
    spaces = size - y
    line = append(line, bytes.Repeat([]byte("\x20"), spaces)...)
    line = append(line, bytes.Repeat(char, count)...)
    line = append(line, bytes.Repeat([]byte("\x20"), spaces)...)
    fmt.Printf("%s\n", line)
    count += 2
}
Output:
|    @    |
|   @@@   |
|  @@@@@  |
| @@@@@@@ |
|@@@@@@@@@|

The second section of the Trifoce contains two triangles separated by a vertical white space. The generation of each figure follows the same rules as the previous triangle so there is no modification here except that each line will contain double the number of characters.

line = append(line, bytes.Repeat([]byte("\x20"), spaces)...)
line = append(line, bytes.Repeat(char, count)...)
line = append(line, bytes.Repeat([]byte("\x20"), spaces)...)

line = append(line, '\x20') /* Vertical Padding */

line = append(line, bytes.Repeat([]byte("\x20"), spaces)...)
line = append(line, bytes.Repeat(char, count)...)
line = append(line, bytes.Repeat([]byte("\x20"), spaces)...)

Notice that we simply duplicated the code that fills the array of characters with a modification in the number of spaces on the right side of the triangle on the left. This additional space on each line will generate the vertical padding that we need to separate the two figures.

|    @    |
|   @@@   |
|  @@@@@  |
| @@@@@@@ |
|@@@@@@@@@|
|    @         @    |
|   @@@       @@@   |
|  @@@@@     @@@@@  |
| @@@@@@@   @@@@@@@ |
|@@@@@@@@@ @@@@@@@@@|

Now we need to center the first triangle by adding the same amount of white spaces on the sides. Visually moving the triangle to the right we find that the required number of spaces for the base is equal to the input N and for each previous line we just need to add one. But since we are going to print these triangle from top to bottom we have to calculate the number of required spaces from y=0 to y=N.

|555554444.444455555| Y=1; S=N+(N-Y); S=5+(5-1) => 4
|55555333...33355555| Y=2; S=N+(N-Y); S=5+(5-2) => 3
|5555522.....2255555| Y=3; S=N+(N-Y); S=5+(5-3) => 2
|555551.......155555| Y=4; S=N+(N-Y); S=5+(5-4) => 1
|55555.........55555| Y=5; S=N+(N-Y); S=5+(5-5) => 0

We change spaces=(size-y) to spaces=(size+(size-y)) for the first triangle.

Now for the final touch, we replace position X=0, Y=0 with a single dot.

To simplify, we can remove the character lists and print directly to I/O:

func solution(size int) {
    var count int = 1
    var spaces int = size + (size - 1)

    fmt.Println("." +
        strings.Repeat("\x20", spaces-1) +
        strings.Repeat("@", count) +
        strings.Repeat("\x20", spaces))
    count += 2

    for y := 2; y <= size; y++ {
        spaces = size + (size - y)
        fmt.Println(strings.Repeat("\x20", spaces) +
            strings.Repeat("@", count) +
            strings.Repeat("\x20", spaces))
        count += 2
    }

    count = 1

    for y := 1; y <= size; y++ {
        spaces = size - y
        fmt.Print(strings.Repeat("\x20", spaces) +
            strings.Repeat("@", count) +
            strings.Repeat("\x20", spaces+1))
        fmt.Println(strings.Repeat("\x20", spaces) +
            strings.Repeat("@", count) +
            strings.Repeat("\x20", spaces))
        count += 2
    }
}
Do you have a project idea? Let's make it together!