-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay18LikeAGifForYourYard.kt
63 lines (52 loc) · 2.18 KB
/
Day18LikeAGifForYourYard.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
package adventofcode.year2015
import adventofcode.Puzzle
import adventofcode.PuzzleInput
import adventofcode.common.Tuple.plus
import adventofcode.common.cartesianProduct
class Day18LikeAGifForYourYard(customInput: PuzzleInput? = null) : Puzzle(customInput) {
override val name = "Like a GIF For Your Yard"
private val initialConfiguration by lazy {
input
.lines()
.flatMapIndexed { y, row -> row.mapIndexed { x, state -> Pair(x, y) to (state == TURNED_ON) } }
.toMap()
}
override fun partOne() =
initialConfiguration.animate()
.drop(1)
.take(STEP_COUNT)
.last()
.count { (_, turnedOn) -> turnedOn }
override fun partTwo() =
initialConfiguration.animate(setOf(Pair(0, 0), Pair(99, 0), Pair(0, 99), Pair(99, 99)))
.drop(1)
.take(STEP_COUNT)
.last()
.count { (_, turnedOn) -> turnedOn }
companion object {
private const val TURNED_ON = '#'
private const val GRID_HEIGHT = 100
private const val GRID_WIDTH = 100
private const val STEP_COUNT = 100
fun Map<Pair<Int, Int>, Boolean>.animate(stuckLights: Set<Pair<Int, Int>> = emptySet()) =
generateSequence(this) { previous ->
previous +
previous.minus(stuckLights).mapNotNull { (light, turnedOn) ->
val turnedOnNeighbors = light.neighbors().count { previous[it]!! }
if (turnedOn && listOf(2, 3).none { turnedOnNeighbors == it }) {
light to false
} else if (!turnedOn && turnedOnNeighbors == 3) {
light to true
} else {
null
}
}
}
private fun Pair<Int, Int>.neighbors() =
listOf((-1..1).toList(), (-1..1).toList())
.cartesianProduct()
.map { this + (it.first() to it.last()) }
.minus(this)
.filter { it.first >= 0 && it.second >= 0 && it.first < GRID_WIDTH && it.second < GRID_HEIGHT }
}
}