-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay23.kt
58 lines (51 loc) · 1.83 KB
/
Day23.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
private val moves = listOf(
Direction.Left to (-1..1).map { Point(-1, it) },
Direction.Right to (-1..1).map { Point(1, it) },
Direction.Down to (-1..1).map { Point(it, -1) },
Direction.Up to (-1..1).map { Point(it, 1) },
)
@OptIn(ExperimentalStdlibApi::class)
private fun wander(tiles: MutableSet<Point>, moveIndex: Int) {
tiles.asSequence()
.filter { point ->
moves.any { neighbours -> neighbours.second.any { point + it in tiles } }
}
.mapNotNull { point ->
moves[moveIndex..<moves.size].asSequence()
.plus(moves[0..<moveIndex].asSequence())
.find { (_, scope) -> scope.none { point + it in tiles } }
?.let { point + it.first.point to point }
}
.groupBy({ it.first }) { it.second }
.asSequence()
.filter { it.value.size == 1 }
.forEach { (to, from) ->
tiles -= from.single()
tiles += to
}
}
private fun part1(originalTiles: Set<Point>): Int {
val tiles = originalTiles.toMutableSet()
repeat(10) { wander(tiles, it % moves.size) }
return (tiles.minOf { it.x }..tiles.maxOf { it.x }).sumOf { i ->
(tiles.minOf { it.y }..tiles.maxOf { it.y }).count { Point(i, it) !in tiles }
}
}
private fun part2(originalTiles: Set<Point>): Int {
val tiles = originalTiles.toMutableSet()
repeat(Int.MAX_VALUE) { i ->
val copy = tiles.toSet()
wander(tiles, i % moves.size)
if (tiles == copy) return i + 1
}
error("Int.MAX_VALUE iterations, huh?")
}
fun main() {
val tiles = buildSet {
getFullInput().lineSequence().forEachIndexed { i, row ->
row.asSequence().withIndex().filter { it.value == '#' }.forEach { add(Point(i, it.index)) }
}
}
println(part1(tiles))
println(part2(tiles))
}