66 lines
2.1 KiB
Kotlin
66 lines
2.1 KiB
Kotlin
package be.vandewalleh.aoc.days
|
|
|
|
import be.vandewalleh.aoc.utils.input.Day
|
|
import be.vandewalleh.aoc.utils.input.Lines
|
|
import org.eclipse.collections.api.bag.Bag
|
|
import org.eclipse.collections.api.bag.MutableBag
|
|
import org.eclipse.collections.api.factory.Bags
|
|
|
|
@Day(24)
|
|
class Day24(@Lines val input: List<String>) {
|
|
|
|
private data class HexPoint(val x: Int, val y: Int, val z: Int) {
|
|
fun translate(other: HexPoint) = HexPoint(this.x + other.x, this.y + other.y, this.z + other.z)
|
|
}
|
|
|
|
private enum class Direction(vararg coordinates: Int) {
|
|
E(1, -1, 0),
|
|
SE(0, -1, 1),
|
|
SW(-1, 0, 1),
|
|
W(-1, 1, 0),
|
|
NW(0, 1, -1),
|
|
NE(1, 0, -1);
|
|
|
|
val coordinates = HexPoint(coordinates[0], coordinates[1], coordinates[2])
|
|
}
|
|
|
|
private fun parseTile(line: String) = "e|se|sw|w|nw|ne".toRegex()
|
|
.findAll(line)
|
|
.flatMap { it.groupValues }
|
|
.map { Direction.valueOf(it.toUpperCase()) }
|
|
.toList()
|
|
|
|
private val tiles = input.map { parseTile(it) }.map {
|
|
it.map { it.coordinates }.reduce { acc, ints -> acc.translate(ints) }
|
|
}
|
|
|
|
fun part1() = Bags.immutable.ofAll(tiles).selectBlacks().size()
|
|
|
|
private fun Bag<HexPoint>.selectBlacks() = selectByOccurrences { it % 2 == 1 }
|
|
|
|
private fun HexPoint.adjacents() = Direction.values().map { this.translate(it.coordinates) }
|
|
|
|
// black -> odd
|
|
// white -> even || not in bag -> !in black
|
|
private fun day(bag: MutableBag<HexPoint>) {
|
|
val blacks = bag.selectBlacks().toSet()
|
|
|
|
val all = (bag + bag.flatMap { it.adjacents() }).toSet()
|
|
|
|
for (tile in all) {
|
|
val adjacents = tile.adjacents()
|
|
val adjacentBlacks = adjacents.count { it in blacks }
|
|
val isBlack = tile in blacks
|
|
|
|
if (isBlack && (adjacentBlacks == 0 || adjacentBlacks > 2)) bag.setOccurrences(tile, 2)
|
|
else if (!isBlack && adjacentBlacks == 2) bag.setOccurrences(tile, 1)
|
|
}
|
|
}
|
|
|
|
fun part2(): Int {
|
|
val bag = Bags.mutable.ofAll(tiles)
|
|
repeat(100) { day(bag) }
|
|
return bag.selectBlacks().size()
|
|
}
|
|
}
|