class BrickStack(snapShot: List) { val brickStack: List init { val fallingBricks = snapShot.map { val brickDescription = it.split("~").map { coords -> coords.split(",").map(String::toInt) } Brick( brickDescription[0][0]..brickDescription[1][0], brickDescription[0][1]..brickDescription[1][1], brickDescription[0][2]..brickDescription[1][2] ) }.sortedBy { brick -> brick.z.first } val fallenBricks = mutableListOf() fallingBricks.forEach { brick -> var fallingBrick = brick var supported = false while (!supported) { val supportingBricks = fallenBricks.filter { it.x.intersect(fallingBrick.x).isNotEmpty() && it.y.intersect(fallingBrick.y).isNotEmpty() && it.z.last == fallingBrick.z.first - 1 } supported = supportingBricks.isNotEmpty() || fallingBrick.z.first == 0 if (supported) { supportingBricks.forEach { it.addOnTop(fallingBrick) fallingBrick.addSupport(it) } fallenBricks += fallingBrick } else { val nextZ = fallenBricks.filter { it.z.last < fallingBrick.z.first - 1 } .maxBy { it.z.last }?.z?.last?.let { it + 1 } ?: 0 val brickHeight = fallingBrick.z.last - fallingBrick.z.first fallingBrick = Brick( fallingBrick.x, fallingBrick.y, nextZ .. nextZ + brickHeight ) } } } // fallenBricks.forEach { // println("${it.supportedBy} <- [[$it]] -> ${it.supports}") // } brickStack = fallenBricks } fun findBricksToTake(): List = brickStack.filter { brickToTake -> !brickToTake.supports.any { it.supportedBy.size == 1 } } fun howManyWillFall(): Int { val bricksWithEffect = brickStack.filter { brickToTake -> brickToTake.supports.any { it.supportedBy.size == 1 } } return bricksWithEffect.sumBy { takenBrick -> val collapsingStack = brickStack.toMutableList() collapsingStack.remove(takenBrick) val bricksGone = mutableListOf(takenBrick) do { val unsupported = collapsingStack.filter { it.supportedBy.isNotEmpty() && it.supportedBy.all { support -> bricksGone.contains(support) } } collapsingStack.removeAll(unsupported) bricksGone.addAll(unsupported) } while (unsupported.isNotEmpty()) bricksGone.size - 1 } } } class Brick(val x: IntRange, val y: IntRange, val z: IntRange) { val supports = mutableListOf() val supportedBy = mutableListOf() fun addOnTop(other: Brick) { supports += other } fun addSupport(other: Brick) { supportedBy += other } override fun toString(): String { return "[$x,$y,$z]" } }