Den 18. byl tak trochu variací na “The Game of Life”, kde druhou část jsem již vyřešil s trochou matematické magie 🙂 .
import com.ichipsea.kotlin.matrix.*
import com.svetylkovo.adventofcode2018.day18.Acre.*
import com.svetylkovo.adventofcode2018.toNonSeparatedPrettyString
import com.svetylkovo.adventofcode2018.trimmedNonBlankLines
import java.io.File
enum class Acre(val sign: Char) {
GROUND('.'), TREE('|'), LUMBERYARD('#');
override fun toString() = "$sign"
}
fun parseAcre(sign: Char) = when (sign) {
TREE.sign -> TREE
LUMBERYARD.sign -> LUMBERYARD
else -> GROUND
}
class Area(var area: Matrix<Acre>) {
fun nextMinute() {
area = area.mapIndexed { x, y, acre -> getMutatedAcre(x, y) }
}
private fun getMutatedAcre(x: Int, y: Int): Acre {
val adjacent = getAdjacent(x, y)
val acre = area[x, y]
return when (acre) {
GROUND -> if (adjacent.count { it == TREE } >= 3) TREE else acre
TREE -> if (adjacent.count { it == LUMBERYARD } >= 3) LUMBERYARD else acre
LUMBERYARD -> if (adjacent.count { it == LUMBERYARD } > 0 && adjacent.count { it == TREE } > 0) acre else GROUND
}
}
fun getAdjacent(origX: Int, origY: Int): List<Acre> {
return (origX - 1..origX + 1)
.asSequence()
.filter { it in 0 until area.cols }
.map { x ->
(origY - 1..origY + 1)
.asSequence()
.filter { it in 0 until area.rows }
.filterNot { y -> x == origX && y == origY }
.map { y -> area[x, y] }
}.flatten().toList()
}
fun count(acre: Acre) = area.toList().count { it == acre }
fun getResourceValue() = count(TREE) * count(LUMBERYARD)
override fun toString() = area.toNonSeparatedPrettyString()
}
fun parseArea(input: String): Area {
val lines = input.trimmedNonBlankLines()
val width = lines[0].length
val height = lines.size
val matrix = lines
.flatMap { it.map(::parseAcre) }
.toMatrix(width, height)
return Area(matrix)
}
fun main() {
val input = File("input18.txt").readText()
//A
val areaA = parseArea(input)
repeat(10) { areaA.nextMinute() }
println(areaA.getResourceValue())
//B
val areaB = parseArea(input)
val magicCache = mutableMapOf<Int, Int>()
val magicPeriodConstant = 28
val magicDiff = 610
repeat(magicDiff - 1) { areaB.nextMinute() }
repeat(magicPeriodConstant) {
areaB.nextMinute()
magicCache += it to areaB.getResourceValue()
}
println(magicCache[(1000000000 - magicDiff) % magicPeriodConstant])
}