✨ Advent of Code — Day 02 <2021 />

Day 2: Dive!

Cf. aoc. d. ii

Let’s dive into the challenge and explore the depths of the ocean * with our submarine! 🌊

I’ll take you through my thought process as I approached this challenge and explain how I came up with my solution. So, grab a cup of coffee and let’s dive into the challenge! ☕️

If you want to go straight to the code, you can check it out on our codelicia’s repository.


PART 1

* The raw payload is something like the following:
forward 5
down 5
forward 8
up 3
down 8
forward 2

As always the first thing we need to do is to parse the input. The input for this problem is a list of strings. Each string represents a command to the submarine. The command is composed by an orientation and a number. The orientation can be * forward, up, down. The number is the distance the submarine should move in the given orientation.

My first thought was to represent each direction as a tuple. The first element of the tuple would be the orientation and the second element would be the distance.

class Day02(plannedCourse: List<String>) {

    val submarine =
        plannedCourse
            .map {
                val (orientation, to) = it.split(" ")
                orientation to to.toInt()
            }
            
}

fun Day02.submarine(): List<Pair<String, Int>> = this.submarine

fun main(): Unit = println(Day02(listOf( "forward 5", "down 5", "forward 8", "up 3", "down 8", "forward 2" )).submarine())

If you think about it, we don’t need to iterate over the list of commands and increment/decrement the depth. We can just sum all the distances and subtract the up distances from the down distances. The result will be the depth of the submarine.

I’ve created a helper function sumOfCoordinate to sum all the distances of a given orientation.

class Day02(plannedCourse: List<String>) {

    val submarine =
        plannedCourse
            .map {
                val (orientation, to) = it.split(" ")
                orientation to to.toInt()
            }
            
    private fun List<Pair<String, Int>>.sumOfCoordinate(coordinate: String): Int =
        this.filter { it.first == coordinate }.sumOf { it.second }
        
}

fun Day02.submarine(): List<Pair<String, Int>> = this.submarine

fun main(): Unit = println(Day02(listOf( "forward 5", "down 5", "forward 8", "up 3", "down 8", "forward 2" )).submarine())

Now we can use the sumOfCoordinate function to calculate the depth of the submarine. When multiplying by the forward it will give us the distance traveled by the submarine.

class Day02(plannedCourse: List<String>) {

    val submarine =
        plannedCourse
            .map {
                val (orientation, to) = it.split(" ")
                orientation to to.toInt()
            }
            
    private fun List<Pair<String, Int>>.sumOfCoordinate(coordinate: String): Int =
        this.filter { it.first == coordinate }.sumOf { it.second }
        
    fun part1(): Int =
        submarine.sumOfCoordinate("down")
            .minus(submarine.sumOfCoordinate("up"))
            .times(submarine.sumOfCoordinate("forward"))
}

fun Day02.submarine(): List<Pair<String, Int>> = this.submarine

fun main(): Unit = println(Day02(listOf( "forward 5", "down 5", "forward 8", "up 3", "down 8", "forward 2" )).part1())

We’ve got our first star! 🌟


PART 2

Unfortunately, for the second part of the challenge, we can’t use the same approach. We need to iterate over the list of commands and calculate the depth of the submarine for each command and calculate the aim. But it still pretty straightforward.

class Day02(plannedCourse: List<String>) {

    val submarine =
        plannedCourse
            .map {
                val (orientation, to) = it.split(" ")
                orientation to to.toInt()
            }
            
    private fun List<Pair<String, Int>>.sumOfCoordinate(coordinate: String): Int =
        this.filter { it.first == coordinate }.sumOf { it.second }
        
    fun part1(): Int =
        submarine.sumOfCoordinate("down")
            .minus(submarine.sumOfCoordinate("up"))
            .times(submarine.sumOfCoordinate("forward"))
            
    fun part2(): Int {

        var depth = 0
        var horizontal = 0
        var aim = 0

        submarine
            .forEach { x ->
                when (x.first) {
                    "down" -> aim += x.second
                    "up" -> aim -= x.second
                    "forward" -> {
                        depth += (aim * x.second)
                        horizontal += x.second
                    }
                }
            }

        return horizontal * depth
    }
}

fun Day02.submarine(): List<Pair<String, Int>> = this.submarine

fun main(): Unit {
   println("Part 1: " + Day02(listOf( "forward 5", "down 5", "forward 8", "up 3", "down 8", "forward 2" )).part1())
   println("Part 2: " + Day02(listOf( "forward 5", "down 5", "forward 8", "up 3", "down 8", "forward 2" )).part2())
}

Yay! We’ve got our second star! 🌟