Advent of Code in Kotlin 2021 - Day 13
This is part 13 of a series, so if you haven't read the previous parts, start here.
For today's puzzle we are given a list of 2D positions representing dots and a set of instructions on how to fold the paper. As we apply the folds, the position of the dots has to be adjusted accordingly and some dots overlap.
I worked out a simple formula for adjusting dot positions with pen and paper and wrote up a bit of code to apply a fold to a set of dots.
private data class Fold(val axis: Axis, val position: Int)
private enum class Axis {
X, Y;
companion object {
fun of(input: String): Axis = if (input[11] == 'x') X else Y
}
}
private fun applyFold(dots: Set<Pair<Int, Int>>, fold: Fold): Set<Pair<Int, Int>> = when (fold.axis) {
Axis.X -> dots.map { (x, y) ->
if (x > fold.position) Pair(2 * fold.position - x, y) else Pair(x, y)
}
Axis.Y -> dots.map { (x, y) ->
if (y > fold.position) Pair(x, 2 * fold.position - y) else Pair(x, y)
}
}.toSet()
For part 1, we just have to apply the first fold and count the number of dots after adjusting for overlapping. For part 2 we have to apply all the folds. Afterwards, the remaining dots spell out eight capital letters as ASCII art. I ended up using the fold method to fold the folds (😂), printed the ASCII art to screen and visually read the result.
private fun part1(dots: Set<Pair<Int, Int>>, folds: List<Fold>): Int = applyFold(dots, folds.first()).size
private fun part2(dots: Set<Pair<Int, Int>>, folds: List<Fold>): String {
val foldedDots = folds.fold(dots) { d, fold -> applyFold(d, fold) }
val xRange = 0..foldedDots.maxOf { it.first }
val yRange = 0..foldedDots.maxOf { it.second }
return yRange.joinToString(System.lineSeparator()) { y ->
xRange.map { x -> if (foldedDots.contains(Pair(x, y))) '#' else '.' }.joinToString("")
}
}
fun main() {
val input = inputLines(2021, 13)
val dots =
input.takeWhile { it.isNotBlank() }.map { it.split(",") }.map { Pair(it.first().toInt(), it.last().toInt()) }
.toSet()
val folds = input.drop(dots.size + 1).map { Fold(Axis.of(it), it.substringAfter("=").toInt()) }
println(part1(dots, folds))
println(part2(dots, folds))
}
Another quick one, not too bad at all. That's two more stars in the bag.