Skip to content

Commit 7f2b194

Browse files
committed
Day 19
1 parent 02b02da commit 7f2b194

File tree

6 files changed

+90
-24
lines changed

6 files changed

+90
-24
lines changed

aoc-secret

src/main/kotlin/com/cluddles/aoc/util/Int2d.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@ data class Int2d(val x: Int, val y: Int) {
1717

1818
/** Manhattan distance: sum of absolute [x] and [y] */
1919
fun manhattan(): Int = x.absoluteValue + y.absoluteValue
20+
/** Manhattan distance: absolute [x] and [y] difference */
21+
fun manhattan(o: Int2d): Int = (o.x - x).absoluteValue + (o.y - y).absoluteValue
2022

2123
}

src/main/kotlin/com/cluddles/aoc/y2024/Day18.kt

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,7 @@ import com.cluddles.aoc.util.Int2d
99
import com.cluddles.aoc.util.IntGrid
1010
import java.util.*
1111

12-
/**
13-
* RAM Run
14-
*
15-
* Thought I was smart by noticing that the grid size (from `0,0` to `70,70`) is actually 71x71
16-
*
17-
* The myriad of mistakes I made after this might suggest otherwise:
18-
* * Reading is hard. We don't just want to add all the interruptions to the grid immediately.
19-
* * Reading is hard again. For a moment I thought we wanted to have the interruptions appear as we traverse.
20-
* * `x = x + d.y` was a painful typo that took me a while to spot
21-
*
22-
* Initial implementation as quick and easy depth-first search, which is good enough to get the answers.
23-
*
24-
* Input grid contains the "tick" that each cell becomes obstructed.
25-
*/
12+
/** RAM Run */
2613
object Day18: Solver<Grid<Int>, String> {
2714

2815
override fun prepareInput(src: SolverInput): Grid<Int> {
@@ -41,10 +28,8 @@ object Day18: Solver<Grid<Int>, String> {
4128
// A* to find lowest cost path from start to end
4229
private fun lowestCost(start: Int2d, end: Int2d, grid: Grid<Int>, tick: Int): Int? {
4330
val g = mutableMapOf<Int2d, Int>()
44-
val f = mutableMapOf<Int2d, Int>()
45-
val open = PriorityQueue<Int2d>(Comparator.comparingInt { f[it]!! })
31+
val open = PriorityQueue<Int2d>(Comparator.comparingInt { g[it]!! + it.manhattan(end) })
4632
g[start] = 0
47-
f[start] = (end - start).manhattan()
4833
open += start
4934
while (open.isNotEmpty()) {
5035
val current = open.remove()
@@ -59,7 +44,6 @@ object Day18: Solver<Grid<Int>, String> {
5944
}
6045
.forEach {
6146
g[it] = gNext
62-
f[it] = gNext + (end - it).manhattan()
6347
open += it
6448
}
6549
}
@@ -82,11 +66,7 @@ object Day18: Solver<Grid<Int>, String> {
8266
while (max - min > 1) {
8367
val current = (min + max) / 2
8468
val valid = (solvePart1(input, current) != Int.MAX_VALUE)
85-
if (valid) {
86-
min = current
87-
} else {
88-
max = current
89-
}
69+
if (valid) min = current else max = current
9070
}
9171
return with (input.iterableWithPos().first { it.data == min }) { "$x,$y" }
9272
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.cluddles.aoc.y2024
2+
3+
import com.cluddles.aoc.core.Harness
4+
import com.cluddles.aoc.core.Solver
5+
import com.cluddles.aoc.core.SolverInput
6+
import kotlin.collections.mutableMapOf
7+
8+
/** Linen Layout */
9+
object Day19: Solver<Day19.Input, Long> {
10+
11+
data class Input(val patterns: List<String>, val towels: List<String>)
12+
13+
override fun prepareInput(src: SolverInput): Input {
14+
return Input(src.lines().first().split(", "), src.lines().drop(1).toList())
15+
}
16+
17+
/** Can [towel] be constructed from given [patterns]. Store known results in [cache]. */
18+
fun isPossible(
19+
towel: String,
20+
patterns: List<String>,
21+
cache: MutableMap<String, Boolean> = mutableMapOf()
22+
): Boolean {
23+
return cache[towel] ?: patterns
24+
.filter { p -> towel.startsWith(p) }
25+
.any { p -> if (p == towel) true else isPossible(towel.substring(p.length), patterns, cache) }
26+
.also { cache[towel] = it }
27+
}
28+
29+
/** Count ways [towel] can be constructed from [patterns]. Store known results in [cache]. */
30+
fun countPossibilities(
31+
towel: String,
32+
patterns: List<String>,
33+
cache: MutableMap<String, Long> = mutableMapOf()
34+
): Long {
35+
return cache[towel] ?: patterns
36+
.filter { p -> towel.startsWith(p) }
37+
.sumOf { p -> if (p == towel) 1L else countPossibilities(towel.substring(p.length), patterns, cache) }
38+
.also { cache[towel] = it }
39+
}
40+
41+
override fun solvePart1(input: Input): Long {
42+
return input.towels.count { isPossible(it, input.patterns) }.toLong()
43+
}
44+
45+
override fun solvePart2(input: Input): Long {
46+
return input.towels.sumOf { countPossibilities(it, input.patterns) }
47+
}
48+
49+
}
50+
51+
fun main() {
52+
Harness.run(Day19)
53+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.cluddles.aoc.y2024
2+
3+
import com.cluddles.aoc.core.SolverInput
4+
import org.assertj.core.api.Assertions.assertThat
5+
import org.junit.jupiter.api.Test
6+
7+
class Day19Test {
8+
9+
val solver = Day19
10+
11+
val input = solver.prepareInput(SolverInput.fromPath(solver.examplePath))
12+
13+
@Test fun part1() {
14+
assertThat(solver.solvePart1(input)).isEqualTo(6)
15+
}
16+
17+
@Test fun part2() {
18+
assertThat(solver.solvePart2(input)).isEqualTo(16)
19+
}
20+
21+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
r, wr, b, g, bwu, rb, gb, br
2+
3+
brwrr
4+
bggr
5+
gbbr
6+
rrbgbr
7+
ubwu
8+
bwurrg
9+
brgr
10+
bbrgwb

0 commit comments

Comments
 (0)