-
Notifications
You must be signed in to change notification settings - Fork 0
/
aoc-11.kts
100 lines (69 loc) · 2.56 KB
/
aoc-11.kts
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// https://adventofcode.com/2021/day/11
import java.io.File
import kotlin.collections.ArrayDeque
fun input() = File("input/aoc-11.txt").readLines()
data class Point(val x: Int, val y: Int)
data class Matrix(val n: Int, private val def: Int = 0) : Iterable<Point> {
private val data = Array(n) { Array<Int>(n) { def } }
operator fun get(p: Point) = data[p.y][p.x]
operator fun set(p: Point, z: Int) { data[p.y][p.x] = z }
fun adj(p: Point) = sequenceOf(
Point(p.x, p.y - 1),
Point(p.x + 1, p.y - 1),
Point(p.x + 1, p.y),
Point(p.x + 1, p.y + 1),
Point(p.x, p.y + 1),
Point(p.x - 1, p.y + 1),
Point(p.x - 1, p.y),
Point(p.x - 1, p.y - 1),
).filter { q -> q.x >= 0 && q.x < n && q.y >= 0 && q.y < n }
override fun iterator(): Iterator<Point> = object : Iterator<Point> {
private var i = 0
override fun next() = Point(i % n, i / n).also { i++ }
override fun hasNext() = i < n*n
}
override fun toString() = data.map { r -> r.joinToString("") }.joinToString("\n")
}
fun Matrix(lines: List<String>) = Matrix(lines.size).apply {
lines.forEachIndexed { y, line ->
line.forEachIndexed { x, c -> this[Point(x, y)] = c.toString().toInt() }
}
}
// Part 1.
fun p1(input: List<String>): Int {
val dumbos = Matrix(input)
fun flash(p: Point) = dumbos.adj(p).filter { ++dumbos[it] > 9 }
fun step(): Int {
val done = mutableSetOf<Point>()
val pending = ArrayDeque<Point>()
dumbos.forEach { p -> if (++dumbos[p] > 9) pending.addLast(p) }
while (pending.isNotEmpty()) {
val p = pending.removeLast()
if (done.add(p)) pending += flash(p)
}
dumbos.forEach { p -> if (dumbos[p] > 9) dumbos[p] = 0 }
return done.size
}
return (0 until 100).sumOf { step() }
}
// Part 2.
fun p2(input: List<String>): Int {
val dumbos = Matrix(input)
fun flash(p: Point) = dumbos.adj(p).filter { ++dumbos[it] > 9 }
fun step(): Boolean {
val done = mutableSetOf<Point>()
val pending = ArrayDeque<Point>()
dumbos.forEach { p -> if (++dumbos[p] > 9) pending.addLast(p) }
while (pending.isNotEmpty()) {
val p = pending.removeLast()
if (done.add(p)) pending += flash(p)
}
dumbos.forEach { p -> if (dumbos[p] > 9) dumbos[p] = 0 }
return dumbos.all { p -> dumbos[p] == 0 }
}
return generateSequence(1, Int::inc).first { step() }
}
with(input()) {
println(p1(this)) // 1691
println(p2(this)) // 216
}