-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay17.kt
67 lines (61 loc) · 2.63 KB
/
Day17.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
59
60
61
62
63
64
65
66
67
typealias Rock = Set<Pair<Int, Int>>
fun main() {
val input = readInputText("Day17")
val grid = (0..6).map { it to 0 }.toMutableSet()
var i = 0
var top = 0
var added = 0L
var rocksDropped = 0L
val totalRocksToDrop = 1000000000000
val seen = mutableMapOf<Any, Pair<Long, Int>>()
fun Rock.moveLeft() = if (any { it.first == 0 }) this else map { it.first - 1 to it.second }.toSet()
fun Rock.moveRight() = if (any { it.first == 6 }) this else map { it.first + 1 to it.second }.toSet()
fun Rock.moveUp() = map { it.first to it.second + 1 }.toSet()
fun Rock.moveDown() = map { it.first to it.second - 1 }.toSet()
fun getRock(i: Int, y: Int) = listOf(
setOf(2 to y, 3 to y, 4 to y, 5 to y),
setOf(3 to y + 2, 2 to y + 1, 3 to y + 1, 4 to y + 1, 3 to y),
setOf(2 to y, 3 to y, 4 to y, 4 to y + 1, 4 to y + 2),
setOf(2 to y, 2 to y + 1, 2 to y + 2, 2 to y + 3),
setOf(2 to y + 1, 2 to y, 3 to y + 1, 3 to y)
)[i]
while (rocksDropped < totalRocksToDrop) {
var rock = getRock((rocksDropped % 5).toInt(), top + 4)
while (true) {
if (input[i] == '<') {
rock = rock.moveLeft()
if (rock.intersect(grid).isNotEmpty())
rock = rock.moveRight()
} else {
rock = rock.moveRight()
if (rock.intersect(grid).isNotEmpty())
rock = rock.moveLeft()
}
i = (i + 1) % input.length
rock = rock.moveDown()
if (rock.intersect(grid).isNotEmpty()) {
rock = rock.moveUp()
grid += rock
top = grid.maxOf { it.second }
val maxY = grid.maxOf { it.second }
val topGrid = grid.map { it.first to maxY - it.second }.filter { it.second <= 30 }.toSet()
val key = Triple(i, rocksDropped % 5, topGrid)
if (key in seen && rocksDropped >= 2022) {
val (oldRocksDropped, oldTop) = seen[key]!!
val heightDiff = top - oldTop
val dropped = rocksDropped - oldRocksDropped
val cyclesCount = (totalRocksToDrop - rocksDropped) / dropped
added += cyclesCount * heightDiff
rocksDropped += dropped * cyclesCount
assert(rocksDropped <= totalRocksToDrop)
}
seen[key] = rocksDropped to top
break
}
}
rocksDropped++
if (rocksDropped == 2022L)
println("Part 1: $top")
}
println("Part 2: ${top + added}")
}