Day 12, finish part 2 + refactoring

This commit is contained in:
Sven Weidauer 2024-12-14 13:04:15 +01:00
parent 6c5111b38c
commit b8411307bb
2 changed files with 42 additions and 39 deletions

View file

@ -1,21 +1,19 @@
fun main() { fun main() {
var part1 = 0 var part1 = 0
var part2 = 0 var part2 = 0
while (all.isNotEmpty()) { while (all.isNotEmpty()) {
val start = all.elementAt(0) val start = all.elementAt(0)
val (area, fenceLength, fenceSides) = input.floodFill(start) val (area, fenceLength, fenceSides) = input.floodFill(start)
part1 += area * fenceLength part1 += area * fenceLength
part2 += area * fenceSides part2 += area * fenceSides
println("$area x $fenceSides")
} }
println("Part 1: $part1") println("Part 1: $part1")
println("Part 2: $part2") println("Part 2: $part2")
} }
val input = CharGrid.read("day12-sample.txt") val input = CharGrid.read("day12.txt")
val all = sequence { val all = sequence {
for (y in 0..<input.height) { for (y in 0..<input.height) {
for (x in 0..<input.width) { for (x in 0..<input.width) {
@ -32,33 +30,29 @@ fun CharGrid.floodFill(start: Grid.Coordinate): Triple<Int, Int, Int> {
all.removeAll(visited) all.removeAll(visited)
println(fence.horizontalSides.flatMap { it.value.sides.values.toSet().map { side -> it.key to side} })
println(fence.verticalSides.flatMap { it.value.sides.values.toSet().map { side -> it.key to side} })
return Triple(visited.count(), fence.length, fence.sides) return Triple(visited.count(), fence.length, fence.sides)
} }
class Fence { class Fence {
var length = 0
val sides
get() = horizontalSides.values.fold(0) { acc, sides -> acc + sides.count } +
verticalSides.values.fold(0) { acc, sides -> acc + sides.count }
fun add(coordinate: Grid.Coordinate, horizontal: Boolean) {
length += 1
if (horizontal) {
horizontalSides.getOrPut(coordinate.y) { SideList() }.add(coordinate.x)
} else {
verticalSides.getOrPut(coordinate.x) { SideList() }.add(coordinate.y)
}
}
val horizontalSides = mutableMapOf<Int, SideList>() val horizontalSides = mutableMapOf<Int, SideList>()
val verticalSides = mutableMapOf<Int, SideList>() val verticalSides = mutableMapOf<Int, SideList>()
val length
get() = horizontalSides.values.sumOf { it.length } +
verticalSides.values.sumOf { it.length }
data class Side(val start: Int, val end: Int = start) { val sides
get() = horizontalSides.values.sumOf { it.count } +
verticalSides.values.sumOf { it.count }
fun add(coordinate: Grid.Coordinate, horizontal: Boolean, first: Boolean) {
if (horizontal) {
horizontalSides.getOrPut(coordinate.y) { SideList() }.add(coordinate.x, first)
} else {
verticalSides.getOrPut(coordinate.x) { SideList() }.add(coordinate.y, first)
}
}
data class Side(val first: Boolean, val start: Int, val end: Int = start) {
init { init {
require(start <= end) require(start <= end)
} }
@ -67,20 +61,22 @@ class Fence {
} }
class SideList { class SideList {
val sides = mutableMapOf<Int, Side>() val sidesByPosition = mutableMapOf<Int, Side>()
val count: Int get() = sides.values.toSet().count() val sides: Set<Side> get() = sidesByPosition.values.toSet()
val count: Int get() = sides.count()
val length: Int get() = sides.sumOf { it.length }
fun add(position: Int) { fun add(position: Int, first: Boolean) {
if (sides.containsKey(position)) return if (sidesByPosition.containsKey(position)) return
val before = sides[position - 1] val before = sidesByPosition[position - 1]?.takeIf { it.first == first }
val after = sides[position + 1] val after = sidesByPosition[position + 1]?.takeIf { it.first == first }
val newSide = when { val newSide = when {
before != null && after != null -> Side(before.start, after.end) before != null && after != null -> Side(first, before.start, after.end)
before != null -> Side(before.start, position) before != null -> Side(first, before.start, position)
after != null -> Side(position, after.end) after != null -> Side(first, position, after.end)
else -> Side(position) else -> Side(first, position)
} }
assert(before == null || newSide.start == before.start) assert(before == null || newSide.start == before.start)
@ -88,10 +84,10 @@ class Fence {
assert(position in newSide.start..newSide.end) assert(position in newSide.start..newSide.end)
for (pos in newSide.start..newSide.end) { for (pos in newSide.start..newSide.end) {
sides[pos] = newSide sidesByPosition[pos] = newSide
} }
assert(sides[position] === newSide) assert(sidesByPosition[position] === newSide)
} }
} }
@ -108,7 +104,9 @@ fun CharGrid.floodFill(start: Grid.Coordinate, type: Char, visited: MutableSet<G
} }
if (!inside(neighbor) || this[neighbor] != type) { if (!inside(neighbor) || this[neighbor] != type) {
fence.add(neighbor, direction == Direction.North || direction == Direction.South) val first = direction == Direction.North || direction == Direction.West
val fencePosition = if (first) neighbor else start
fence.add(fencePosition, direction == Direction.North || direction == Direction.South, first)
} }
} }
} }

View file

@ -1,5 +1,10 @@
EEEEE RRRRIICCFF
EXXXX RRRRIICCCF
EEEEE VVRRRCCFFF
EXXXX VVRCCCJFFF
EEEEE VVVVCJJCFE
VVIVCCJJEE
VVIIICJJEE
MIIIIIJJEE
MIIISIJEEE
MMMISSJEEE