1
0
This commit is contained in:
2020-12-11 08:06:45 +01:00
parent 34259208d5
commit b7ba2d10a7
2 changed files with 216 additions and 0 deletions
+123
View File
@@ -0,0 +1,123 @@
package be.vandewalleh.aoc.days
import be.vandewalleh.aoc.utils.input.Day
import be.vandewalleh.aoc.utils.input.Input
import be.vandewalleh.aoc.utils.input.Lines
import be.vandewalleh.aoc.utils.input.createDay
typealias Seats = Array<CharArray>
fun Seats.deepClone(): Seats = map { it.clone() }.toTypedArray()
operator fun Seats.get(x: Int, y: Int): Char = this[y][x]
operator fun Seats.set(x: Int, y: Int, value: Char) {
this[y][x] = value
}
operator fun Seats.contains(xy: Pair<Int, Int>): Boolean {
val (x, y) = xy
return x in 0 until width && y in 0 until height
}
val Seats.width get() = first().size
val Seats.height get() = size
fun Seats.asGridString() = joinToString("\n") { it.joinToString("") }
fun Seats.countOccupied() = sumBy { it.count { it == '#' } }
@Day(11)
class Day11(@Lines val input: Input<List<String>>) {
private val seats: Seats = input.value.map { it.toCharArray() }.toTypedArray()
private val directions = listOf(
-1 to -1,
+0 to -1,
+1 to -1,
+1 to +0,
+1 to +1,
+0 to +1,
-1 to +1,
-1 to +0,
)
private fun countAdjacentOccupiedSeats(x: Int, y: Int, seats: Array<CharArray>): Int =
directions.mapNotNull { (dx, dy) ->
val xx = x + dx
val yy = y + dy
if (xx to yy in seats) seats[xx, yy]
else null
}.count { it == '#' }
private fun countVisibleOccupiedSeats(x: Int, y: Int, seats: Seats): Int {
var occupied = 0
for ((dx, dy) in directions) {
var xx = x
var yy = y
while (true) {
xx += dx
yy += dy
if (xx to yy !in seats) break
if (seats[xx, yy] == 'L') break
if (seats[xx, yy] == '#') {
occupied++
break
}
}
}
return occupied
}
private fun findLastRepeating(seats: Seats, next: (Seats) -> Seats): Seats {
var previous = seats
val set = HashSet<String>() // use strings because Arrays don't implement equals ??
while (true) {
val res = next(previous)
if (!set.add(res.asGridString())) return res
previous = res
}
}
private fun progress1(previous: Array<CharArray>): Array<CharArray> {
val next = previous.deepClone()
for (x in 0 until seats.width) {
for (y in 0 until seats.height) {
when (previous[x, y]) {
'L' -> if (countAdjacentOccupiedSeats(x, y, previous) == 0) next[x, y] = '#'
'#' -> if (countAdjacentOccupiedSeats(x, y, previous) >= 4) next[x, y] = 'L'
}
}
}
return next
}
fun part1() = findLastRepeating(seats, ::progress1).countOccupied()
private fun progress2(previous: Seats): Array<CharArray> {
val next = previous.deepClone()
for (x in 0 until previous.width) {
for (y in 0 until previous.height) {
when (previous[x, y]) {
'L' -> if (countVisibleOccupiedSeats(x, y, previous) == 0) next[x, y] = '#'
'#' -> if (countVisibleOccupiedSeats(x, y, previous) >= 5) next[x, y] = 'L'
}
}
}
return next
}
fun part2() = findLastRepeating(seats, ::progress2).countOccupied()
}
fun main() = with(createDay<Day11>()) {
println(part1())
println(part2())
}