🔴 Day 2 - Red-Nosed Reports Link to heading
Day 2, let’s go! For today, our input consists of a list of Int
s per line, split by space, so parsing was as easy as
val input = Path("Day02.txt")
.readLines()
.map {
it.split(" ").map { it.toInt() }
}
and our test input is:
7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9
Part 1 Link to heading
For Part 1, we need to check how many lists are strict monotonic functions, for which all members do not differ by more than 3 but no less than 1 from their neighbours.
To do that, I used List<Int>.windowed(2)
to iterate over two elements at the same time, and partly reused my solution from Part 1 of yesterday to calculate the distance, and just added the check for the max and min distance.
input.count {
it.windowed(2).map { (current, next) ->
0 < abs(current - next) <= 3 && current < next
}.all { it } || it.windowed(2).map { (current, next) ->
0 < abs(current - next) <= 3 && current > next
}.all { it }
}
This could have been done a lot cleaner, but it works so 🤷♂️, outputting 2
.
Part 2 Link to heading
Part 2 was basically the same, but with the extra rule that per list, one item can be out of line and still be considered “ordered right”. The simplest way I could think of was to just reuse the code from Part 1, but bruteforce every possible alteration of the list by removing one element each.
Sadly, the kotlin stdlib is missing a removeAt()
method for immutable lists that just returns a copy with the missing element, so I came up with this:
inline fun < reified T> List<T>.removeAt(i: Int) = filterIndexed { index, _ -> index != i }
And modified the old code to brute-force the result:
input.count { l ->
(0..l.size-1).any { i ->
l.removeAt(i).let { it ->
it.windowed(2).map { (current, next) ->
0 < abs(current - next) <= 3 && current < next
}.all { it } || it.windowed(2).map { (current, next) ->
0 < abs(current - next) <= 3 && current > next
}.all { it }
}
}
}
Outputting 4
, and securing us both stars for today!