-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day18LikeAGifForYourYard.kt
58 lines (47 loc) · 2 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
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 }
}
}