diff --git a/2024/src/main/kotlin/day9.kt b/2024/src/main/kotlin/day9.kt index 05f7834..9a3ded9 100644 --- a/2024/src/main/kotlin/day9.kt +++ b/2024/src/main/kotlin/day9.kt @@ -8,6 +8,7 @@ sealed class Span { fun main() { var currentFileId = 0 + val input = readInputString("day9.txt").mapIndexed { index, c -> if (index % 2 == 0) { Span.File(currentFileId++, c.digitToInt()) @@ -17,6 +18,7 @@ fun main() { } println("Part 1: ${part1(input)}") + println("Part 2: ${part2(input)}") } private fun part1(input: List): Long { @@ -38,8 +40,42 @@ private fun part1(input: List): Long { } } - val checkSum = disk.calculateCheckSum() - return checkSum + return disk.calculateCheckSum() +} + +private fun part2(input: List): Long { + val disk = input.toMutableList() + + var index = disk.lastIndex + while (index > 0) { + val file = disk[index] + if (file !is Span.File) { + --index + continue + } + + val target = disk.subList(0, index).indexOfFirst { + it is Span.Empty && it.length >= file.length + } + + if (target != -1) { + disk[index] = Span.Empty(file.length) + + val space = disk[target] + + require(space is Span.Empty) + + disk[target] = file + if (space.length > file.length) { + disk.add(target + 1, Span.Empty(space.length - file.length)) + ++index + } + } + + --index + } + + return disk.calculateCheckSum() } private fun MutableList.takeFileBlocksFromEnd(blocks: Int): Span.File { @@ -62,10 +98,11 @@ private fun List.calculateCheckSum(): Long { var currentBlock = 0L for (file in this) { - require(file is Span.File) - - repeat(file.length) { - checkSum += currentBlock++ * file.id + when (file) { + is Span.Empty -> currentBlock += file.length + is Span.File -> repeat(file.length) { + checkSum += currentBlock++ * file.id + } } }