Advent of Code 2021 - Day 2

Here we are again, continuing Advent of Code 2021! We're moving into Day 2 now, so let's get right into it!

The Problems Continue

Continuing from yesterday's misadventures, we find ourselves still on our submarine moving forward unto dawn.  We need to figure out how to control the submarine and find that it can take in a series of commands, and that the commands are preprogrammed.  We have to thus decipher exactly where we're being taken by our submarine!

Commands come in three flavors: Forward, down, and up.  Forward works exactly like you expect, it moves the submarine forward.  Up and down adjust depth, of course, but because we are tracking our depth, we have to remember that down increases our depth while up decreases it.  Commands also have a number associated with it, which dictates how much of any given command we do.  forward 3 for example would mean we have to add 3 to our horizontal tracker.  Finally, we're tasked with finding the sum of the horizontal position and our depth.  No big deal, let's dive right in.

First off, let's consider our problem input: a list of commands.  While we could, of course, take in a list of string commands and parse things from there we can do better.  We'll define a data class and use that to represent our actual commands.  Each command has two parts, the direction and the amount.  As such, we can use a data class that looks like this:

data class Command(val direction: String, val amount: Long)

Simple yet effective. Now we just need to write a simple iterator over a list of commands to track our space:

fun day2(commands: List<Command>): Long {
    var horizontal = 0L
    var vertical = 0L
    commands.forEach { command ->
        when (command.direction) {
            "forward" -> horizontal += command.amount
            "down" -> vertical += command.amount
            "up" -> vertical -= command.amount
        }
    }
    return horizontal * vertical
}

And there we go! A nice, simple solution.  For each command we get we check what the command direction is, then apply to appropriate modification to our horizontal and vertical variables.  The last thing we do is, of course, a simple summation of the value.  If we use the test data:

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

we get a total sum of 150 (15 horizontal [5 + 8 + 3] times 10 depth [5 - 3 + 8]).  And with that we earn our first star.

But the problems keep on rolling in

Part 2 of today is a nice riff on the original problem.  Apparently, after solving our data, we find that we were TOTALLY wrong about how the submarine works, and after a quick read of the manual (which as developers we absolutely skipped in our initial implementation) we come to find out there is in fact 3 things we need to track: Horizontal space, Depth, and Aim.  Those up and down commands we thought dictated our actual depth? Totally wrong, not even close.  Those dictate how the submarine is aimed.  Imagine a simple tube moving left to right, when a down command is applied, we tilt our tube so that the left side points downward by the amount given:

Forgive the terrible art, I hope this helps visualize the scenario!

To get the actual depth we instead need to consider what happens when we move forward.  The submarine instruction manual explains that if our aim is 2, and we move forward 4, we move downward by the sum of our aim and our forward movement, so our depth increases by 8.  To put it plainly, Depth = Depth + (Horitzonal Amount * Aim).  Finally, we want to once again understand the sum of our total horitzonal movement and our depth.  With all of that out of the way, let's get to our code:

fun day2Part2(commands: List<Command>): Long {
    var horizontal = 0L
    var vertical = 0L
    var aim = 0L
    commands.forEach { command ->
        when (command.direction) {
            "forward" -> {
                horizontal += command.amount
                vertical += command.amount * aim
            }
            "down" -> aim += command.amount
            "up" -> aim -= command.amount
        }
    }
    return horizontal * vertical
}

Our code now is much the same as it was before, but with the aim variable factored in.  Instead of down and up impacting our depth directly, we just impact our aim, and the forward condition resolves the actual depth calculation, along with the horizontal tracking.  Given the same test data of above we get a satisfying 900, and earning our second gold star.

And that's it! Day 2 is closed out.  What does the sea floor hold in store for us in our haphazard attempt to save Christmas (and likely the jobs of the elves)? What kind of monster design a submarine that is incapable of turning left or right, or receiving directional control from those riding in it? Some of these answers and more as Advent of Code 2021 continues tomorrow!