# Advent of Code 2023 - Day 6, in Kotlin - Wait For It

Kotlin solutions to parts 1 and 2 of Advent of Code 2023, Day 6: 'Wait For It'

Posted on

What a fun problem! I’m sure there’s some clever quadratic math one could apply to get an answer without doing any kind of looping at all, but I’m happy with what I did here.

If you’d rather just view the code, my GitHub Repository is here.

Puzzle Input

We will take our puzzle input in as a `List<String>` and define it as a private property because each part of the puzzle requires separate parsing.

``````class Day06(private val input: List<String>) {

}
``````

Running The Race

Instead of following the puzzle text, let’s think about what we expect to see. There are some set of races where we don’t wait long enough that we expect to not set a record. Correspondingly, at the other end of the spectrum there is another set of races where we wait too long. Rather than scanning the entire possible range of races, let’s come at this from both ends.

For example:

``````
-------------------------time---------------------------->
--scan up--->                             <---scan down---

Race Results
--------------
s = Too Slow
R = New Record

``````

We will scan UP from 1 second (since 0 makes no sense, we can’t ever set a record that way) and find the first race we set a record for. Then we scan DOWN from the highest time until we set a record. The difference between these numbers (minus one, see below) is our answer.

``````// In Day06

private fun race(time: Long, distance: Long): Long {
val start = (1 .. time).first { hold ->
((time-hold)) * hold > distance
} -1

val end = (time downTo 1).first { hold ->
((time-hold)) * hold > distance
}

return end-start
}
``````

In order to run a `race` we take in the `time` and `distance` record. We’ll do all of this with `Long` instead of `Int` because the numbers get longer in part 2. As stated in the strategy above, we set up a range to look at times starting at 1 and take the `first` one where there is a record. Because we want to only count non-winners, we need to subtract by 1 here. The inner calculation figures out the distance we travel given a `hold` time, and measures it against the `distance` record.

The second range works the same way, except we go backwards from the end of the time period to the beginning, finding the `first` race where we set a record.

#### ⭐ Day 6, Part 1

The puzzle text can be found here.

Other than parsing, the `race` function does all of our work for us!

``````// In Day06

fun solvePart1(): Long {
val times = input.first().substringAfter(":").split(" ")
.filter { it.isNotEmpty() }.map { it.toLong() }
val distances = input.drop(1).first().substringAfter(":").split(" ")
.filter { it.isNotEmpty() }.map { it.toLong() }

return times.zip(distances)
.map { race(it.first, it.second) }
.reduce(Long::times)
}
``````

Parsing is done like in days previous - take the `substringAfter` the `:`, `split` it by space, remove anything that is empty, and `map` to Long. The only difference between parsing `times` and `distances` is dropping the first row of input.

In order to run the races and calculate the product, we will `zip` the `times` and `distances` together. For each pair of them, this will give us a `Pair<Long,Long>` where the `first` element is the `time` and the `second` element is the `distance`. We could probably iterate over one of these lists and look up the other by index, but I like this better.

We run each `race` and then using `reduce`, we multiply the results together via the `Long::times` function.

Running this gives us our answer.

Star earned! Onward!

#### ⭐ Day 6, Part 2

The puzzle text can be found here.

Again, since `race` does all the work we need, we can parse our input and run it directly.

``````// In Day06

fun solvePart2(): Long {
val time = input.first().substringAfter(":")
.filter { it.isDigit() }.toLong()
val distance = input.drop(1).first().substringAfter(":")
.filter { it.isDigit() }.toLong()

return race(time, distance)
}
``````

Parsing is very similar to part 1 except we filter out anything that isn’t a digit. The `race` function is run as-is and gives us our answer quickly.

Star earned! See you tomorrow!