From 5ae3381d7489e9292b00a2e9b3f8cd9b6c1fae86 Mon Sep 17 00:00:00 2001 From: Daniel Lin Date: Sat, 14 Dec 2024 10:09:07 -0500 Subject: [PATCH] Day 14: Restroom Redoubt --- README.md | 2 +- .../ephemient/aoc2024/exe/Day14Bench.kt | 31 ++++++++++++ .../com/github/ephemient/aoc2024/Day14.kt | 47 +++++++++++++++++++ .../com/github/ephemient/aoc2024/Days.kt | 1 + .../com/github/ephemient/aoc2024/Day14Test.kt | 29 ++++++++++++ 5 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 kt/aoc2024-exe/src/commonBench/kotlin/com/github/ephemient/aoc2024/exe/Day14Bench.kt create mode 100644 kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day14.kt create mode 100644 kt/aoc2024-lib/src/commonTest/kotlin/com/github/ephemient/aoc2024/Day14Test.kt diff --git a/README.md b/README.md index 70e0c52..b0662be 100644 --- a/README.md +++ b/README.md @@ -18,4 +18,4 @@ Development occurs in language-specific directories: |[Day11.hs](hs/src/Day11.hs)|[Day11.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day11.kt)|[day11.py](py/aoc2024/day11.py)|[day11.rs](rs/src/day11.rs)| |[Day12.hs](hs/src/Day12.hs)|[Day12.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day12.kt)|[day12.py](py/aoc2024/day12.py)|| |[Day13.hs](hs/src/Day13.hs)|[Day13.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day13.kt)|[day13.py](py/aoc2024/day13.py)|| -|[Day14.hs](hs/src/Day14.hs)|||| +|[Day14.hs](hs/src/Day14.hs)|[Day14.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day14.kt)||| diff --git a/kt/aoc2024-exe/src/commonBench/kotlin/com/github/ephemient/aoc2024/exe/Day14Bench.kt b/kt/aoc2024-exe/src/commonBench/kotlin/com/github/ephemient/aoc2024/exe/Day14Bench.kt new file mode 100644 index 0000000..8eb3b44 --- /dev/null +++ b/kt/aoc2024-exe/src/commonBench/kotlin/com/github/ephemient/aoc2024/exe/Day14Bench.kt @@ -0,0 +1,31 @@ +package com.github.ephemient.aoc2024.exe + +import com.github.ephemient.aoc2024.Day14 +import kotlinx.benchmark.Benchmark +import kotlinx.benchmark.Blackhole +import kotlinx.benchmark.Scope +import kotlinx.benchmark.Setup +import kotlinx.benchmark.State + +@State(Scope.Benchmark) +class Day14Bench { + private lateinit var input: String + + @Setup + fun setup() { + input = getDayInput(14) + } + + @Benchmark + fun part1() = Day14(input).part1() + + @Benchmark + fun part2() = Day14(input).part2() + + @Benchmark + fun solve(bh: Blackhole) { + val day14 = Day14(input) + bh.consume(day14.part1()) + bh.consume(day14.part2()) + } +} diff --git a/kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day14.kt b/kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day14.kt new file mode 100644 index 0000000..37ec7b4 --- /dev/null +++ b/kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day14.kt @@ -0,0 +1,47 @@ +package com.github.ephemient.aoc2024 + +class Day14(input: String) { + private val robots = input.lineSequence().mapNotNull { + val (x, y, vx, vy) = pattern.matchEntire(it)?.destructured ?: return@mapNotNull null + Robot(x.toInt(), y.toInt(), vx.toInt(), vy.toInt()) + }.toList() + + fun part1(width: Int = WIDTH, height: Int = HEIGHT): Int { + val quadrants = IntArray(4) + for (robot in robots) { + val x = (robot.x + robot.vx * 100).mod(width) + val y = (robot.y + robot.vy * 100).mod(height) + quadrants[ + (if (x < width / 2) 0 else if (x > width / 2) 1 else continue) or + if (y < height / 2) 0 else if (y > height / 2) 2 else continue + ]++ + } + println(quadrants.toList()) + return quadrants.fold(1, Int::times) + } + + fun part2() = (0.. + val positions = robots.mapTo(mutableSetOf()) { robot -> + (robot.x + robot.vx * t).mod(WIDTH) to (robot.y + robot.vy * t).mod(HEIGHT) + }.sortedWith(compareBy(IntPair::second, IntPair::first)) + var consecutive = 1 + var maxConsecutive = 0 + for ((i, pos) in positions.withIndex()) { + if (pos.first + 1 to pos.second == positions.getOrNull(i + 1)) { + consecutive += 1 + } else { + maxConsecutive = maxOf(consecutive, maxConsecutive) + consecutive = 1 + } + } + t to maxConsecutive + }.maxBy(IntPair::second).also(::println).first + + private data class Robot(val x: Int, val y: Int, val vx: Int, val vy: Int) + + companion object { + private const val WIDTH = 101 + private const val HEIGHT = 103 + private val pattern = """p=(-?\d+),(-?\d+) v=(-?\d+),(-?\d+)""".toRegex() + } +} diff --git a/kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Days.kt b/kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Days.kt index ab96ff8..30e2368 100644 --- a/kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Days.kt +++ b/kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Days.kt @@ -14,6 +14,7 @@ val days: List = listOf( Day(11, ::Day11, Day11::part1, Day11::part2), Day(12, ::Day12, Day12::part1, Day12::part2), Day(13, ::Day13, Day13::part1, Day13::part2), + Day(14, ::Day14, Day14::part1, Day14::part2), ) data class Day( diff --git a/kt/aoc2024-lib/src/commonTest/kotlin/com/github/ephemient/aoc2024/Day14Test.kt b/kt/aoc2024-lib/src/commonTest/kotlin/com/github/ephemient/aoc2024/Day14Test.kt new file mode 100644 index 0000000..cfe5dab --- /dev/null +++ b/kt/aoc2024-lib/src/commonTest/kotlin/com/github/ephemient/aoc2024/Day14Test.kt @@ -0,0 +1,29 @@ +package com.github.ephemient.aoc2024 + +import kotlin.test.Test +import kotlin.test.assertEquals + +class Day14Test { + @Test + fun part1() { + assertEquals(12, Day14(example).part1(11, 7)) + } + + companion object { + val example = + """ + |p=0,4 v=3,-3 + |p=6,3 v=-1,-3 + |p=10,3 v=-1,2 + |p=2,0 v=2,-1 + |p=0,0 v=1,3 + |p=3,0 v=-2,-2 + |p=7,6 v=-1,-3 + |p=3,0 v=-1,-2 + |p=9,3 v=2,3 + |p=7,3 v=-1,2 + |p=2,4 v=2,-3 + |p=9,5 v=-3,-3 + |""".trimMargin() + } +}