Skip to content

Commit

Permalink
Day 9: Disk Defragmenter
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient committed Dec 9, 2024
1 parent b85bfb4 commit 7c02626
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ Development occurs in language-specific directories:
|[Day6.hs](hs/src/Day6.hs)|[Day6.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day6.kt)|[day6.py](py/aoc2024/day6.py)|[day6.rs](rs/src/day6.rs)|
|[Day7.hs](hs/src/Day7.hs)|[Day7.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day7.kt)|[day7.py](py/aoc2024/day7.py)|[day7.rs](rs/src/day7.rs)|
|[Day8.hs](hs/src/Day8.hs)|[Day8.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day8.kt)|[day8.py](py/aoc2024/day8.py)|[day8.rs](rs/src/day8.rs)|
|[Day9.hs](hs/src/Day9.hs)||||
|[Day9.hs](hs/src/Day9.hs)|[Day9.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day9.kt)|||
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.github.ephemient.aoc2024.exe

import com.github.ephemient.aoc2024.Day9
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.Setup
import kotlinx.benchmark.State

@State(Scope.Benchmark)
class Day9Bench {
private lateinit var input: String

@Setup
fun setup() {
input = getDayInput(9)
}

@Benchmark
fun part1() = Day9(input).part1()

@Benchmark
fun part2() = Day9(input).part2()

@Benchmark
fun solve(bh: Blackhole) {
val day9 = Day9(input)
bh.consume(day9.part1())
bh.consume(day9.part2())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.github.ephemient.aoc2024

class Day9(input: String) {
private val input = input.mapNotNull { it.digitToIntOrNull() }

fun part1(): Long {
val chunks = input.toIntArray()
var total = 0L
var i = 0
var j = chunks.lastIndex
var offset = 0
while (i <= j) {
if (i % 2 == 0) {
val size = chunks[i]
total += i / 2L * triRange(offset, size)
offset += size
i++
} else if (j % 2 == 0) {
val free = chunks[i]
val size = chunks[j]
total += j / 2L * triRange(offset, minOf(free, size))
offset += minOf(free, size)
if (free <= size) i++ else chunks[i] = free - size
if (free >= size) j-- else chunks[j] = size - free
} else {
j--
}
}
return total
}

fun part2(): Long {
val files = IntArray((input.size + 1) / 2) { input[2 * it] }
val frees = IntArray(input.size / 2) { input[2 * it + 1] }
val offsets = IntArray(input.size)
for (i in 0..offsets.size - 2) offsets[i + 1] = offsets[i] + input[i]
var total = 0L
outer@for (i in files.lastIndex downTo 0) {
val size = files[i]
for (j in 0 until i) {
if (frees[j] >= size) {
total += i.toLong() * triRange(offsets[2 * j + 1], size)
frees[j] -= size
offsets[2 * j + 1] += size
continue@outer
}
}
total += i.toLong() * triRange(offsets[2 * i], size)
}
return total
}

companion object {
private fun triRange(offset: Int, size: Int) = (2 * offset + size - 1) * size / 2
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ val days: List<Day> = listOf(
Day(6, ::Day6, Day6::part1, Day6::part2),
Day(7, ::Day7, Day7::part1, Day7::part2),
Day(8, ::Day8, Day8::part1, Day8::part2),
Day(9, ::Day9, Day9::part1, Day9::part2),
)

data class Day(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.github.ephemient.aoc2024

import kotlin.test.Test
import kotlin.test.assertEquals

class Day9Test {
@Test
fun part1() {
assertEquals(1928L, Day9(example).part1())
}

@Test
fun part2() {
assertEquals(2858L, Day9(example).part2())
}

companion object {
private val example =
"""
|2333133121414131402
|""".trimMargin()
}
}

0 comments on commit 7c02626

Please sign in to comment.