Advent of Code in Go: #13

3 minute read

In this series I explore the Advent of Code, or AoC for short, with the Go programming language. Every day, as real life permits, I will be solving a puzzle from the series. I will document each day with a solution in Go and a walkthrough of the code.

You can find the previous walkthroughs here.

The puzzle

Today we are going to try and get a packet through a firewall. There are guards at multiple layers of the firewall that patrol a certain depth, back and forth.

The firewall is visualized in nice ASCII diagrams and a step by step walkthrough explains the conditions of the puzzle. Lets take a look at one such diagram:

Picosecond 0:
 0   1   2   3   4   5   6
(S) [S] ... ... [S] ... [S]
[ ] [ ]         [ ]     [ ]
[ ]             [ ]     [ ]
                [ ]     [ ]

At picosecond 0 all the gaurds are at the top of their layer. I enter the layer as well, indicated with a ( ). As I enter the layer while the guard is at index 0 I get caught. If we continue this proces, with the guards moving a square each picosecond and I move a layer I will get caught at step 0 and 6.

The formula to determine if a guard is at the 0th index at any given picosecond seems to be the following: picosecond % (depth * 2). As the guard moves back and forth I need to multiply the depth by 2.

The puzzle asks to calculate the severity of you getting caught in the firewall. The given conditions for this are:

The severity of getting caught on a layer is equal to its depth multiplied by its range The severity of the whole trip is the sum of these values. In the example above, the trip severity is 0*3 + 6*4 = 24.

Part 2 of the puzzle asks to calculate the delay required in order to traverse the firewall without getting caught. The formula changes a little bit to (delay + picoseconds) % (depth * 2). As you might have noticed I already applied this to the below function. Using the multi value return of Go again it allows me to answer both questions with a single function. The trick here is that getting caught in layer 0 results in a severity of 0. So if you only get caught there, you cannot use severity as an indication of being caught.

To calculate the severity we increase the depth by 1 again. In the input the depth is given without regard that arrays start counting from 0.

func caught(firewall []int, delay int) (c bool, severity int) {
	for pico := 0; pico < len(firewall); pico++ {
		if firewall[pico] > 0 {
			guardpos := (delay + pico) % (firewall[pico] * 2)
			if guardpos == 0 {
				severity += pico * (firewall[pico] + 1)
				c = true
			}
		}
	}
	return
}

The driver program for this is simply parsing the input and then returning the values of part 1 and 2 to the unit test code. I decrease the depth of the layer by 1 to account for the count from 0 in arrays. Then the only thing left to do is to solve the 2 puzzles.

func solve(input []string) (part1 int, part2 int, err error) {
	conv := func(in string) []string {
		return strings.Split(in, ": ")
	}

	max := conv(input[len(input)-1])

	firewall := make([]int, atoi(max[0])+1)
	for _, v := range input {
		vals := conv(v)
		firewall[atoi(vals[0])] = atoi(vals[1]) - 1
	}

	_, part1 = caught(firewall, 0)

	c := true
	for c == true {
		part2++
		c, _ = caught(firewall, part2)
	}

	return
}

And thats a wrap for day 13. Tomorrow I have a party, so I will not be doing a puzzle then, I hope to get caught up again on friday.

Tags: , ,

Updated: