Advent Of Code - Day 2

Here we go for day 2!

These first couple of problems prepare you on how to deal with input mainly. Learn and get used to parsing lines, and get comfortable with data structures.

Day 2 - Part 1

We continue the story of Santa and the submarine. This time, he has the task of trying to steer the thing. The task is straightforward. You get a couple of instructions and based on a value you increase or decrease a positions.

We have a choice to make here. The wording says horizontal position and depth. Considering the future of these exercises we could go with variable names horizontal and depth. But I choose x and y. Why did I do that? That sounds like I’m not considering the right variable names. But I’m preparing for the inevitable 2D coordinates that will definitely come. You might as well get comfortable dealing with them now.

So, what are our constraints?

This time, it’s quite clear and neatly packaged:

  • forward X increases the horizontal position by X units.
  • down X increases the depth by X units.
  • up X decreases the depth by X units.

Now comes a sentence I think is there only to confuse you. It might be not, but I swear I had to take a second look at that. The above constraints are clear and easy to follow. And then comes this sentence and makes me take spend a little bit more time on parsing them:

Note that since you’re on a submarine, down and up affect your depth, and so they have the opposite result of what you might expect.

No, they are not. According to the constraints I expect down to increase depth and up to decrease depth. It’s clearly written there. I believe this sentence should just be ignored.

Let’s get to solving this thing. We read the rest of the thing, and get to our test input.

forward 5
down 5
forward 8
up 3
down 8
forward 2

What comes now, is trying to parse the input. In Go, Scanf is an option. In other languages, you might want to just Split(s, " ") split by space. In Go I’m using this:

		var (
			op string
			v  int
		)
		fmt.Sscanf(string(l), "%s %d", &op, &v)

What’s happening here is that l is a line from the above sample in a file ( reading line by line ). "%s %d" is saying scan for strings and then scan for a number. And the &op, &v just puts the result in their respective values.

We have the result now in values. Let’s implement the above three rules.

switch op {
case "forward":
    x += v
case "up":
    y -= v
case "down":
    y += v
}

Pretty neat. Could be an if. Could be made tidier. Doesn’t really matter as long as it solves the problem at hand. Competitive scripts usually are not meant to be maintainable masterpieces.

It gets the job done. Then we continue by reading what the actual result should be and we see that we just have to multiple horizontal position with depth. Which is x * y.

fmt.Println("mult: ", x*y)

This gets us the right test value and, in fact, the right value to our input as well.

Here, I would like to mention that you always have to deal with things like empty new lines, and spaces after a line. So always trim and make sure you don’t accidentally parse an empty line as a valid input.

Day 2 - Part 2

Now, things get a bit more complex. Turns out we aren’t actually parsing the coordinates correctly, so there are some new constraints. What are they?

We have a new value, aim. And a new set of constraints:

  • down X increases your aim by X units.
  • up X decreases your aim by X units.
  • forward X does two things:
    • It increases your horizontal position by X units.
    • It increases your depth by your aim multiplied by X.

Again, just ignore the fluff around this this time, because it’s more distracting than helpful. Sometimes it contains some weird extra info, but this time, I found them to be a bit misleading. The actual problem is super simple.

We change our implementation to increase decrease aim and do the thing for x and y a bit differently.

Following the rules we get to this:

switch op {
case "forward":
    x += v
    y += (aim * v)
case "up":
    aim -= v
case "down":
    aim += v
}

Then we carefully read what has to be done to get the result and we see that it actually did not change. We still multiple x and y.

And indeed, this is the correct result for our test, so we run it for our input and that should yield the right value.

Conclusion

This day now showed you that input comes in various forms and formats which you need to be prepared to parse correctly. We made sure that we skip empty new lines and always trim possible spaces. And we got to know Sscanf which can be handy at times if the format is strict enough.

We also learned to read important information and disregard things which can distract from the actual goal.

The repository for all my solutions for AOC 2021 can be found here.

Thank you for reading!

Happy coding!

Gergely.