Day20 part2 grid assembly
This commit is contained in:
parent
e72f71c1bf
commit
c11231307f
@ -11,10 +11,6 @@ import kotlin.math.sqrt
|
||||
|
||||
private typealias Tile = Grid<Char>
|
||||
|
||||
sealed class TileGroup
|
||||
data class HorizontalGroup(val left: Tile, val right: Tile) : TileGroup()
|
||||
data class VerticalGroup(val top: Tile, val bottom: Tile) : TileGroup()
|
||||
|
||||
@Day(20)
|
||||
class Day20(@Groups val input: Input<List<List<String>>>) {
|
||||
private val tiles: Map<Int, Tile> = input.value
|
||||
@ -28,20 +24,6 @@ class Day20(@Groups val input: Input<List<List<String>>>) {
|
||||
return a.allEdges().any { a -> edges.any { a == it } }
|
||||
}
|
||||
|
||||
private fun group(a: Tile, b: Tile): TileGroup? {
|
||||
for (a: Tile in a.transformations()) {
|
||||
for (b: Tile in b.transformations()) {
|
||||
when {
|
||||
a.firstRow() == b.lastRow() -> return VerticalGroup(top = b, bottom = a)
|
||||
a.firstColumn() == b.lastColumn() -> return HorizontalGroup(left = b, right = a)
|
||||
b.firstRow() == a.lastRow() -> return VerticalGroup(top = a, bottom = b)
|
||||
b.firstColumn() == a.lastColumn() -> return HorizontalGroup(left = a, right = b)
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun combine(tiles: List<Tile>) = sequence {
|
||||
for (i in 0 until tiles.lastIndex) {
|
||||
val a = tiles[i]
|
||||
@ -52,7 +34,7 @@ class Day20(@Groups val input: Input<List<List<String>>>) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun neighbours(): MutableMap<Int, MutableList<Tile>> {
|
||||
private fun tilesByNeighbourCount(): MutableMap<Int, MutableList<Tile>> {
|
||||
val neighbours = combine(tiles.values.toList())
|
||||
.filter { (a, b) -> edgesMatch(a, b) }
|
||||
.map { it.toList() }
|
||||
@ -67,51 +49,81 @@ class Day20(@Groups val input: Input<List<List<String>>>) {
|
||||
return map
|
||||
}
|
||||
|
||||
fun part1() = neighbours()[2]!!
|
||||
.map { tile -> tiles.entries.find { it.value == tile }!!.key.toLong() }
|
||||
.reduce { acc, id -> acc * id }
|
||||
fun part1() = tilesByNeighbourCount()[2]!!
|
||||
.map { tile -> tiles.entries.find { it.value == tile }!!.key.toLong() }
|
||||
.reduce { acc, id -> acc * id }
|
||||
|
||||
fun part2() {
|
||||
private fun neighboursCount(grid: Grid<*>, x: Int, y: Int): Int {
|
||||
var neighboursCount = 2
|
||||
if (x != 0 && x != grid.lastColumnIndex) neighboursCount++
|
||||
if (y != 0 && y != grid.lastRowIndex) neighboursCount++
|
||||
return neighboursCount
|
||||
}
|
||||
|
||||
private fun isLeftOk(grid: Grid<Tile?>, x: Int, y: Int, candidate: Tile) = grid[x - 1, y]
|
||||
?.let { left -> candidate.firstColumn() == left.lastColumn() }
|
||||
?: true
|
||||
|
||||
private fun isTopOk(grid: Grid<Tile?>, x: Int, y: Int, candidate: Tile) = grid[x, y - 1]
|
||||
?.let { top -> candidate.firstRow() == top.lastRow() }
|
||||
?: true
|
||||
|
||||
private fun isBottomOk(grid: Grid<*>, x: Int, y: Int, candidate: Tile, neighbours: MutableMap<Int, MutableList<Tile>>) =
|
||||
if (y == grid.lastRowIndex) true
|
||||
else neighbours[neighboursCount(grid, x, y + 1)]!!
|
||||
.filterNot { it == candidate }
|
||||
.count { it.transformations().any { candidate.lastColumn() == it.firstColumn() } } == 1
|
||||
|
||||
private fun isRightOk(grid: Grid<*>, x: Int, y: Int, candidate: Tile, neighbours: MutableMap<Int, MutableList<Tile>>) =
|
||||
if (x == grid.lastColumnIndex) true
|
||||
else neighbours[neighboursCount(grid, x + 1, y)]!!
|
||||
.filterNot { it == candidate }
|
||||
.count { it.transformations().any { candidate.lastRow() == it.firstRow() } } == 1
|
||||
|
||||
private fun assembleGrid(): Grid<Tile?> {
|
||||
val size = sqrt(tiles.size.toDouble()).toInt()
|
||||
val grid: Grid<Tile?> = Grid(Array(size) { Array(size) { null } })
|
||||
|
||||
val n = neighbours()
|
||||
val neighbours: MutableMap<Int, MutableList<Tile>> = tilesByNeighbourCount()
|
||||
|
||||
val corners = n[2]!!
|
||||
.map { tile -> tiles.entries.find { it.value == tile }!!.key.toLong() }
|
||||
for (y in 0 until grid.height) {
|
||||
for (x in 0 until grid.width) {
|
||||
val neighboursCount = neighboursCount(grid, x, y)
|
||||
val candidates = neighbours[neighboursCount]!!
|
||||
|
||||
check(corners.size == 4)
|
||||
val conditions = mutableListOf<(Tile) -> Boolean>()
|
||||
conditions += { isLeftOk(grid, x, y, it) }
|
||||
conditions += { isTopOk(grid, x, y, it) }
|
||||
|
||||
val borders = n[3]!!
|
||||
.map { tile -> tiles.entries.find { it.value == tile }!!.key.toLong() }
|
||||
// why is this condition needed ?
|
||||
if (x == 0 && y == 0) {
|
||||
conditions += { isBottomOk(grid, x, y, it, neighbours) }
|
||||
conditions += { isRightOk(grid, x, y, it, neighbours) }
|
||||
}
|
||||
|
||||
val insides = n[4]!!
|
||||
.map { tile -> tiles.entries.find { it.value == tile }!!.key.toLong() }
|
||||
var found: Tile? = null
|
||||
|
||||
val groups = combine(tiles.values.toList())
|
||||
.mapNotNull { (a, b) -> group(a, b) }
|
||||
.toList()
|
||||
outer@ for (candidate in candidates) {
|
||||
for (transform in candidate.transformations()) {
|
||||
if (conditions.all { it(transform) }) {
|
||||
found = transform
|
||||
candidates.remove(candidate)
|
||||
break@outer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val groupValues = groups.flatMap {
|
||||
when (it) {
|
||||
is HorizontalGroup -> listOf(it.left, it.right)
|
||||
is VerticalGroup -> listOf(it.top, it.bottom)
|
||||
check(found != null)
|
||||
grid[x, y] = found
|
||||
}
|
||||
}
|
||||
|
||||
val gridArray: Array<Array<Tile?>> = Array(size) { Array(size) { null } }
|
||||
val grid: Grid<Tile?> = Grid(gridArray)
|
||||
return grid
|
||||
}
|
||||
|
||||
val left = groups.filterIsInstance<HorizontalGroup>().map { it.left }.toSet()
|
||||
val right = groups.filterIsInstance<HorizontalGroup>().map { it.right }.toSet()
|
||||
val top = groups.filterIsInstance<VerticalGroup>().map { it.top }.toSet()
|
||||
val bottom = groups.filterIsInstance<VerticalGroup>().map { it.bottom }.toSet()
|
||||
|
||||
println("L:${left.size}")
|
||||
println("R:${right.size}")
|
||||
println("T:${top.size}")
|
||||
println("B:${bottom.size}")
|
||||
|
||||
println(groupValues.filter { it in left && it in top && it !in right && it !in bottom })
|
||||
fun part2() {
|
||||
val grid = assembleGrid()
|
||||
TODO()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -44,13 +44,6 @@ class Grid<T> {
|
||||
|
||||
fun edges() = listOf(row(0), column(0), row(lastRowIndex), column(lastColumnIndex))
|
||||
|
||||
fun neighbours(x: Int, y: Int) = listOf(
|
||||
x to y - 1,
|
||||
x + 1 to y,
|
||||
x to y + 1,
|
||||
x - 1 to y,
|
||||
).mapNotNull { this[x, y] }
|
||||
|
||||
override fun toString() = buildString {
|
||||
data.forEach { line ->
|
||||
append(line.joinToString(""))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user