day(13): add solution
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
a415bf279e
commit
03a4ebbdca
2 changed files with 116 additions and 0 deletions
95
src/year2021/day13/Day13.kt
Normal file
95
src/year2021/day13/Day13.kt
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
package year2021.day13
|
||||||
|
|
||||||
|
import readInput
|
||||||
|
|
||||||
|
enum class Along {
|
||||||
|
X, Y
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Point(val x: Int, val y: Int)
|
||||||
|
|
||||||
|
data class Instruction(val along: Along, val coordinate: Int) {
|
||||||
|
private fun isOver(point: Point): Boolean = when (along) {
|
||||||
|
Along.X -> point.x > coordinate
|
||||||
|
Along.Y -> point.y > coordinate
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun flip(point: Point): Point = when (along) {
|
||||||
|
Along.X -> Point(2 * coordinate - point.x, point.y)
|
||||||
|
Along.Y -> Point(point.x, 2 * coordinate - point.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun execute(points: Set<Point>): Set<Point> {
|
||||||
|
val pointsOverFold = points.filter { isOver(it) }
|
||||||
|
val pointsFlipped = pointsOverFold.map { flip(it) }
|
||||||
|
return points - pointsOverFold.toSet() + pointsFlipped.toSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Origami(private var points: Set<Point>, val instructions: List<Instruction>, private var i: Int = 0) {
|
||||||
|
val visiblePoints: Int
|
||||||
|
get() = points.size
|
||||||
|
|
||||||
|
val instructionsLeft: Boolean
|
||||||
|
get() = i < instructions.size
|
||||||
|
|
||||||
|
fun nextInstruction(): Origami {
|
||||||
|
if (i >= instructions.size) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
points = instructions[i++].execute(points)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String =
|
||||||
|
(0..points.maxOf { it.y }).joinToString("\n") { y ->
|
||||||
|
(0..points.maxOf { it.x }).joinToString("") { x -> if (points.contains(Point(x, y))) "#" else " " }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.toPoint(): Point {
|
||||||
|
val (x, y) = this.split(",").map(String::toInt)
|
||||||
|
return Point(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.toInstruction(): Instruction {
|
||||||
|
val (_, _, description) = this.split(" ")
|
||||||
|
val (axis, coordinate) = description.split("=")
|
||||||
|
return Instruction(if (axis == "x") Along.X else Along.Y, coordinate.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readOrigami(input: List<String>): Origami =
|
||||||
|
input
|
||||||
|
.joinToString("\n")
|
||||||
|
.split("\n\n")
|
||||||
|
.map { it.split("\n") }
|
||||||
|
.let { (points, instructions) ->
|
||||||
|
Origami(
|
||||||
|
points.map(String::toPoint).toSet(),
|
||||||
|
instructions.map(String::toInstruction)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun part1(input: List<String>): Int =
|
||||||
|
readOrigami(input).nextInstruction().visiblePoints
|
||||||
|
|
||||||
|
fun part2(input: List<String>): String {
|
||||||
|
val origami = readOrigami(input)
|
||||||
|
while (origami.instructionsLeft) {
|
||||||
|
origami.nextInstruction()
|
||||||
|
}
|
||||||
|
return origami.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val sample = readInput(13, "sample")
|
||||||
|
val input = readInput(13, "input")
|
||||||
|
|
||||||
|
check(part1(sample) == 17)
|
||||||
|
println(part1(input))
|
||||||
|
|
||||||
|
println(part2(sample))
|
||||||
|
println()
|
||||||
|
println(part2(input))
|
||||||
|
}
|
21
src/year2021/day13/sample.txt
Normal file
21
src/year2021/day13/sample.txt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
6,10
|
||||||
|
0,14
|
||||||
|
9,10
|
||||||
|
0,3
|
||||||
|
10,4
|
||||||
|
4,11
|
||||||
|
6,0
|
||||||
|
6,12
|
||||||
|
4,1
|
||||||
|
0,13
|
||||||
|
10,12
|
||||||
|
3,4
|
||||||
|
3,0
|
||||||
|
8,4
|
||||||
|
1,10
|
||||||
|
2,14
|
||||||
|
8,10
|
||||||
|
9,0
|
||||||
|
|
||||||
|
fold along y=7
|
||||||
|
fold along x=5
|
Loading…
Reference in a new issue