Skip to content

Commit

Permalink
2023 - Day 22 - thx Todd
Browse files Browse the repository at this point in the history
  • Loading branch information
fmmr committed Dec 23, 2023
1 parent 22d8531 commit f9e2dd7
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 13 deletions.
85 changes: 76 additions & 9 deletions src/main/kotlin/no/rodland/advent_2023/Day22.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,93 @@ import no.rodland.advent.Pos3D
// template generated: 22/12/2023
// Fredrik Rødland 2023

class Day22(val input: List<String>) : Day<Long, Long, List<Day22.Brick>> {
// https://todd.ginsberg.com/post/advent-of-code/2023/day22/

class Day22(val input: List<String>) : Day<Int, Int, List<Day22.Brick>> {

private val parsed = input.parse()

override fun partOne(): Long {
return 2
override fun partOne(): Int {
return parsed.size - parsed.structurallySignificant().size
}

override fun partTwo(): Int {
return parsed.structurallySignificant().sumOf { it.topple().size - 1 }
}

private fun Brick.topple(): Set<Brick> = buildSet {
add(this@topple)
val untoppled = (parsed - this).toMutableSet()
do {
val willFall = untoppled
.filter { it.supportedBy.isNotEmpty() }
.filter { it.supportedBy.all { brick -> brick in this } }
.also {
untoppled.removeAll(it)
addAll(it)
}
} while (willFall.isNotEmpty())
}

override fun partTwo(): Long {
return 2
private fun List<Brick>.structurallySignificant(): List<Brick> = filter { brick -> brick.supporting.any { it.supportedBy.size == 1 } }
private fun List<Brick>.settle(): List<Brick> = buildList {
this@settle.forEach { brick ->
var current = brick
do {
var settled = false
val supporters = filter { below -> below.canSupport(current) }
if (supporters.isEmpty() && !current.onGround()) {
val restingPlace = filter { it.z.last < current.z.first - 1 }
.maxOfOrNull { it.z.last }?.let { it + 1 } ?: GROUND
current = current.fall(restingPlace)
} else {
settled = true
supporters.forEach { below -> below.supports(current) }
add(current)
}
} while (!settled)
}
}

data class Brick(val id: Int, val from: Pos3D, val to: Pos3D) : Comparable<Brick> {
val x = from.x..to.x
val y = from.y..to.y
val z = from.z..to.z

val supporting = mutableSetOf<Brick>()
val supportedBy = mutableSetOf<Brick>()


override fun compareTo(other: Brick): Int =
z.first - other.z.first

fun supports(other: Brick) {
supporting += other
other.supportedBy += this
}

fun canSupport(other: Brick): Boolean = x intersects other.x && y intersects other.y && z.last + 1 == other.z.first
fun onGround(): Boolean = z.first == GROUND
fun fall(restingPlace: Int): Brick =
copy(
from = Pos3D(from.x, from.y, restingPlace),
to = Pos3D(to.x, to.y, (restingPlace + (z.last - z.first)))
)

private infix fun IntRange.intersects(other: IntRange): Boolean = first <= other.last && last >= other.first
}

data class Brick(val from: Pos3D, val to: Pos3D)

override fun List<String>.parse(): List<Brick> {
return map { line ->
return mapIndexed { idx, line ->
val (from, to) = line.split('~')
Brick(Pos3D(from), Pos3D(to))
}
Brick(idx, Pos3D(from), Pos3D(to))
}.sorted().settle()
}

override val day = "22".toInt()

companion object {
const val GROUND = 1
}
}
9 changes: 5 additions & 4 deletions src/test/kotlin/no/rodland/advent_2023/Day22Test.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ internal class Day22Test {
private val data22 = "2023/input_22.txt".readFile()
private val test22 = "2023/input_22_test.txt".readFile()

private val resultTestOne = 2L
private val resultTestTwo = 2L
private val resultOne = 2L
private val resultTwo = 2L
private val resultTestOne = 5
private val resultTestTwo = 7
private val resultOne = 497
private val resultTwo = 67468

val test = defaultTestSuiteParseOnInit(
Day22(data22),
Expand All @@ -29,6 +29,7 @@ internal class Day22Test {
resultTwo,
{ Day22(data22) },
{ Day22(test22) },
numInitLive = 2,
)

@Nested
Expand Down

0 comments on commit f9e2dd7

Please sign in to comment.