Skip to content

Commit e09fde7

Browse files
authored
Merge pull request #15 from sraaphorst/D10
Day 10 complete
2 parents 52c8c85 + b88b1b3 commit e09fde7

File tree

5 files changed

+128
-18
lines changed

5 files changed

+128
-18
lines changed

src/main/kotlin/common/intpos2d/intpos2d.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,31 @@ operator fun Int.times(pos: IntPos2D): IntPos2D =
1616

1717
operator fun IntPos2D.times(factor: Int) =
1818
factor * this
19+
20+
enum class Direction(val delta: IntPos2D) {
21+
NORTH(IntPos2D(-1, 0)),
22+
EAST(IntPos2D(0, 1)),
23+
SOUTH(IntPos2D(1, 0)),
24+
WEST(IntPos2D(0, -1));
25+
26+
fun clockwise(): Direction = when (this) {
27+
NORTH -> EAST
28+
EAST -> SOUTH
29+
SOUTH -> WEST
30+
WEST -> NORTH
31+
}
32+
33+
fun counterClockwise(): Direction = when (this) {
34+
NORTH -> WEST
35+
WEST -> SOUTH
36+
SOUTH -> EAST
37+
EAST -> NORTH
38+
}
39+
40+
fun opposite(): Direction = when (this) {
41+
NORTH -> SOUTH
42+
EAST -> WEST
43+
SOUTH -> NORTH
44+
WEST -> EAST
45+
}
46+
}

src/main/kotlin/day06/day06.kt

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,6 @@ package day06
99
import common.aocreader.fetchAdventOfCodeInput
1010
import common.intpos2d.*
1111

12-
/**
13-
* The direction that the guard is facing and moves in.
14-
*/
15-
private enum class Direction(val delta: IntPos2D) {
16-
NORTH(IntPos2D(-1, 0)),
17-
SOUTH(IntPos2D(1, 0)),
18-
EAST(IntPos2D(0, 1)),
19-
WEST(IntPos2D(0, -1));
20-
21-
fun clockwise(): Direction = when (this) {
22-
NORTH -> EAST
23-
EAST -> SOUTH
24-
SOUTH -> WEST
25-
WEST -> NORTH
26-
}
27-
}
28-
2912
private typealias Orientation = Pair<Direction, IntPos2D>
3013

3114
private data class MapGrid(val rows: Int,

src/main/kotlin/day09/day09.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ fun answer2(input: String): BigInteger =
191191
fun main() {
192192
val input = fetchAdventOfCodeInput(2024, 9)
193193

194-
println("--- Day 9: Resonant Collinearity ---")
194+
println("--- Day 9: Disk Fragmenter ---")
195195

196196
// Part 1: 6384282079460
197197
println("Part 1: ${answer1(input)}")

src/main/kotlin/day10/day10.kt

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Advent of Code 2024, Day 09.
2+
// By Sebastian Raaphorst, 2024.
3+
4+
package day10
5+
6+
import common.aocreader.fetchAdventOfCodeInput
7+
import common.intpos2d.*
8+
9+
private typealias Trail = List<IntPos2D>
10+
private typealias Trails = Set<List<IntPos2D>>
11+
12+
private fun parse(input: String): List<List<Int>> =
13+
input.trim().lines()
14+
.map { line -> line.trim().toList().map { it.digitToIntOrNull() ?: -1 } }
15+
16+
private fun findTrails(grid: List<List<Int>>): Map<IntPos2D, Trails> {
17+
val height = grid.size
18+
val width = grid[0].size
19+
20+
val zeros = grid.flatMapIndexed { rowIdx, row ->
21+
row.mapIndexedNotNull { colIdx, height ->
22+
if (height == 0) IntPos2D(rowIdx, colIdx) else null
23+
}
24+
}.toSet()
25+
26+
// For each 9, we want to find the trails that lead to the peak.
27+
fun aux(trailSoFar: Trail): Trails {
28+
val currentPos = trailSoFar.last()
29+
val (currY, currX) = currentPos
30+
val currHeight = grid[currY][currX]
31+
if (currHeight == 9) return setOf(trailSoFar)
32+
33+
// Try all the valid neighbours.
34+
val neighbours = Direction.entries
35+
.map { currentPos + it.delta }
36+
.filter { coords -> coords.first in 0 until height && coords.second in 0 until width }
37+
.filter { coords -> grid[coords.first][coords.second] == currHeight + 1 }
38+
if (neighbours.isEmpty()) return emptySet()
39+
40+
return neighbours.flatMap { pos -> aux(trailSoFar + pos) }.toSet()
41+
}
42+
43+
return zeros.associate { zero -> zero to aux(listOf(zero)) }
44+
}
45+
46+
private fun countTrailheads(trails: Map<IntPos2D, Trails>): Int =
47+
trails.values.sumOf { it.map { it.last() }.toSet().size }
48+
49+
private fun countTrails(trails: Map<IntPos2D, Trails>): Int =
50+
trails.values.sumOf { it.count() }
51+
52+
fun answer1(input: String): Int =
53+
parse(input).let(::findTrails).let(::countTrailheads)
54+
55+
fun answer2(input: String): Int =
56+
parse(input).let(::findTrails).let(::countTrails)
57+
58+
fun main() {
59+
val input = fetchAdventOfCodeInput(2024, 10)
60+
61+
println("--- Day 10: Hoof It ---")
62+
63+
// Part 1: 719
64+
println("Part 1: ${answer1(input)}")
65+
66+
// Part 2: 1530
67+
println("Part 2: ${answer2(input)}")
68+
}

src/test/kotlin/day10/day10.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Advent of Code 2024, Day 10.
2+
// By Sebastian Raaphorst, 2024.
3+
4+
package day10
5+
6+
import org.junit.jupiter.api.Test
7+
import kotlin.test.assertEquals
8+
9+
class Day10Test {
10+
private companion object {
11+
val input =
12+
"""
13+
89010123
14+
78121874
15+
87430965
16+
96549874
17+
45678903
18+
32019012
19+
01329801
20+
10456732
21+
""".trimIndent().trim()
22+
}
23+
24+
@Test
25+
fun `Problem 1 example`() =
26+
assertEquals(36, answer1(input))
27+
28+
@Test
29+
fun `Problem 2 example`() =
30+
assertEquals(81, answer2(input))
31+
}

0 commit comments

Comments
 (0)