diff --git a/src/main/kotlin/com/geistindersh/aoc/year2024/Day9.kt b/src/main/kotlin/com/geistindersh/aoc/year2024/Day9.kt index 1bd5c9a..0dc5bdf 100644 --- a/src/main/kotlin/com/geistindersh/aoc/year2024/Day9.kt +++ b/src/main/kotlin/com/geistindersh/aoc/year2024/Day9.kt @@ -2,6 +2,7 @@ package com.geistindersh.aoc.year2024 import com.geistindersh.aoc.helper.files.DataFile import com.geistindersh.aoc.helper.files.fileToString +import com.geistindersh.aoc.helper.ranges.size import com.geistindersh.aoc.helper.report class Day9( @@ -9,49 +10,43 @@ class Day9( ) { private val blockSectors = fileToString(2024, 9, dataFile) - .map(Char::digitToInt) - .windowed(2, 2, true) - .flatMapIndexed { idx: Int, vals: List -> - if (vals.size == 2) { - listOf(DiskMap.BlockFile(idx, vals.first()), DiskMap.EmptyBlock(vals.last())) - } else { - listOf(DiskMap.BlockFile(idx, vals.first())) + .let { + buildList { + var idx = -1 + for (i in it.indices) { + val size = it[i].digitToInt() + val newBlock = + if (i % 2 == 0) { + idx += 1 + BlockFile(idx, size) + } else { + BlockFile(-1, size) + } + add(newBlock) + } } - }.toList() - - private sealed class DiskMap( - open val size: Int, - ) { - data class BlockFile( - val id: Int, - override val size: Int, - ) : DiskMap(size) - - data class EmptyBlock( - override val size: Int, - ) : DiskMap(size) - } + } + + private data class BlockFile( + val id: Int, + val size: Int, + ) /** - * Convert the list of [DiskMap] into an [IntArray]. + * Convert the list of [BlockFile] into an [IntArray]. * * The id of each of the files is inserted at an appropriate index to match its block * offset. Empty locations are denoted with a value of '-1'. * * @return The block location of each of the files */ - private fun List.toArray(): IntArray { + private fun List.toArray(): IntArray { val size = this.sumOf { it.size } val fileArray = IntArray(size) { -1 } var i = 0 for (file in this) { - when (file) { - is DiskMap.EmptyBlock -> {} - is DiskMap.BlockFile -> { - for (j in 0...toCompactArrayContiguous(): IntArray { + private fun List.toCompactArrayContiguous(): IntArray { val fileArray = this.toArray() // Get ranges for the known empty blocks that we can later fill val emptyBlockRanges = fileArray.emptyBlockRanges() - for (file in this.reversed()) { - when (file) { - is DiskMap.EmptyBlock -> continue - is DiskMap.BlockFile -> { - val insertBlock = emptyBlockRanges.firstOrNull { it.count() >= file.size } ?: continue - val fileStart = fileArray.indexOfFirst { it == file.id } - // Check that the first open spot is before the current file location - if (insertBlock.first > fileStart) continue - - // Move the file, and clear the old position - for (i in 0.. fileStart) break + // Check that the first open spot is before the current file location + val insertBlock = emptyBlockRanges.firstOrNull { it.first < fileStart && it.size() >= file.size } ?: continue + + // Move the file, and clear the old position + for (i in 0..