aoc_2024/day09.kts

117 lines
3.5 KiB
Plaintext
Raw Normal View History

2024-12-09 07:29:10 +00:00
#!/usr/bin/env kotlin
import java.lang.RuntimeException
import java.util.Scanner
val scanner = Scanner(System.`in`)
if (!scanner.hasNext()) {
throw RuntimeException("No input given.")
}
2024-12-11 10:10:10 +00:00
val fileSystem = mutableListOf<Int>()
val fileSystemDesc = scanner.nextLine().split("").filter { it.isNotEmpty() }.map { it.toInt() }.toMutableList()
for (i in 0..fileSystemDesc.lastIndex) {
for (j in 0 until fileSystemDesc[i]) {
if ((i and 1) == 0) {
fileSystem.add(i / 2)
} else {
fileSystem.add(-1)
}
}
}
val compressed = compressPartOne(fileSystem)
val checksumOne = calculateChecksum(compressed)
println("Part one checksum: $checksumOne")
val compressedTwo = compressPartTwo(fileSystem)
val checksumTwo = calculateChecksum(compressedTwo)
println("Part two checksum: $checksumTwo")
fun compressPartOne(fileSystem: MutableList<Int>): MutableList<Int> {
val compressed = fileSystem.toMutableList()
var freeSpacePointer = 0
var lastSectorPointer = compressed.lastIndex
while (freeSpacePointer <= lastSectorPointer) {
if (compressed[freeSpacePointer] != -1) {
freeSpacePointer++
continue
}
if (compressed[lastSectorPointer] == -1) {
lastSectorPointer--
continue
}
val tmp = compressed[freeSpacePointer]
compressed[freeSpacePointer] = compressed[lastSectorPointer]
compressed[lastSectorPointer] = tmp
lastSectorPointer--
freeSpacePointer++
}
return compressed
}
fun calculateChecksum(compressed: MutableList<Int>): Long {
var checksum = 0L
for (i in 0..compressed.lastIndex) {
if (compressed[i] != -1) {
checksum += i.toLong() * compressed[i].toLong()
}
}
return checksum
}
fun compressPartTwo(fileSystem: MutableList<Int>): MutableList<Int> {
val compressed = fileSystem.toMutableList()
var relevantFileId = compressed[compressed.lastIndex]
for (i in compressed.lastIndex downTo 0) {
if (compressed[i] == relevantFileId && relevantFileId >= 0) {
val fileSize = findFileSize(compressed, i, relevantFileId)
val startIndex = findStartIndexOfEmptySpaceOfLength(compressed, fileSize)
if (startIndex != -1 && startIndex < i) {
for (j in 0 until fileSize) {
compressed[startIndex + j] = compressed[i - j]
compressed[i - j] = -1
}
}
relevantFileId--
}
}
return compressed
}
2024-12-09 07:29:10 +00:00
2024-12-11 10:10:10 +00:00
fun findFileSize(compressed: MutableList<Int>, i: Int, relevantFileId: Int): Int {
var fileSize = 0
var j = i
while (j >= 0 && compressed[j] == relevantFileId) {
fileSize++
j--
}
return fileSize
}
fun findStartIndexOfEmptySpaceOfLength(compressed: MutableList<Int>, fileSize: Int): Int {
var startIndex = 0
while (startIndex < compressed.size) {
if (compressed[startIndex] != -1) {
startIndex++
} else {
var emptySpaceLength = 0
for (i in startIndex until (startIndex + fileSize)) {
if (i >= compressed.size) {
return -1
}
if (compressed[i] != -1) {
break
} else {
emptySpaceLength++
}
if (emptySpaceLength == fileSize) {
return startIndex
}
}
startIndex += emptySpaceLength
}
}
return -1
}