Optimized day 9 for no reason, part 2 now runs in about 50ms for really_evil_input.txt.

This commit is contained in:
Chris Hodges 2024-12-10 16:11:38 +01:00
parent abb0225d06
commit 4b84ce2803

View File

@ -2,6 +2,7 @@ package aoc2024
import println import println
import readInput import readInput
import java.util.*
/* /*
--- Day 9: Disk Fragmenter --- --- Day 9: Disk Fragmenter ---
@ -45,24 +46,19 @@ fun main() {
} }
fun part2(input: List<String>): Long { fun part2(input: List<String>): Long {
val diskSize = input[0].sumOf { it - '0' }
val bitmap = IntArray(diskSize) { 0 }
var pos = 0 var pos = 0
var isFile = true var isFile = true
var fileId = 0 var fileId = 0
val freeList = HashMap<Int, MutableList<Int>>() val freeList = Array<MutableSet<Int>>(10) { TreeSet() }
val fileList = ArrayList<Pair<Int, Pair<Int, Int>>>() val fileList = ArrayList<Pair<Int, Pair<Int, Int>>>()
val newFileList = ArrayList<Pair<Int, Pair<Int, Int>>>() val newFileList = ArrayList<Pair<Int, Pair<Int, Int>>>()
for (c in input[0]) { for (c in input[0]) {
val size = c - '0' val size = c - '0'
if (isFile) { if (isFile) {
if (size == 0) println("Narf!")
fileList.add(fileId to (pos to size)) fileList.add(fileId to (pos to size))
fileId++ fileId++
} else { } else {
if (size > 0) { if (size > 0) freeList[size].add(pos)
freeList.getOrPut(size) { ArrayDeque(0) }.add(pos)
}
} }
pos += size pos += size
isFile = !isFile isFile = !isFile
@ -70,35 +66,27 @@ fun main() {
for (file in fileList.reversed()) { for (file in fileList.reversed()) {
val (filePos, size) = file.second val (filePos, size) = file.second
var bestList: MutableList<Int>? = null
var bestListSize = 0 var bestListSize = 0
for (s in size..9) { for (s in size..9) {
val list = freeList[s] val list = freeList[s]
if (list?.isNotEmpty() == true && list[0] < filePos) { val first = list.firstOrNull()
if (bestList == null || list[0] < bestList[0]) { if ((first != null && first < filePos) &&
bestList = list (bestListSize == 0 || first < freeList[bestListSize].first())
) {
bestListSize = s bestListSize = s
} }
} }
} if (bestListSize != 0) {
if (bestList != null) { val newPos = freeList[bestListSize].first()
val newPos = bestList.removeAt(0) freeList[bestListSize].remove(newPos)
if (bestListSize > size) { if (bestListSize > size) freeList[bestListSize - size].add(newPos + size)
val remBucket = freeList.getOrPut(bestListSize - size) { ArrayDeque(0) }
remBucket.add(newPos + size)
remBucket.sort()
}
newFileList.add(file.first to (newPos to size)) newFileList.add(file.first to (newPos to size))
} else { } else {
newFileList.add(file) newFileList.add(file)
} }
} }
for (file in newFileList) { // Gauß to the rescue!
for (i in 0 until file.second.second) { return newFileList.sumOf { it.first * (it.second.first.toLong() * it.second.second + (it.second.second * (it.second.second - 1) / 2)) }
bitmap[i + file.second.first] = file.first
}
}
return bitmap.map(Int::toLong).reduceIndexed { index, acc, i -> acc + index * i }
} }
// test if implementation meets criteria from the description, like: // test if implementation meets criteria from the description, like: