diff --git a/src/year2021/day13/Day13.kt b/src/year2021/day13/Day13.kt new file mode 100644 index 0000000..a8f53a4 --- /dev/null +++ b/src/year2021/day13/Day13.kt @@ -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): Set { + 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, val instructions: List, 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): 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): Int = + readOrigami(input).nextInstruction().visiblePoints + +fun part2(input: List): 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)) +} diff --git a/src/year2021/day13/sample.txt b/src/year2021/day13/sample.txt new file mode 100644 index 0000000..32a8563 --- /dev/null +++ b/src/year2021/day13/sample.txt @@ -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 \ No newline at end of file