Compare commits
No commits in common. "abb0225d064653bd8ff228d71667c3e1bce2cbae" and "26661cbfd8f6100d9565a33208309873d4ee366e" have entirely different histories.
abb0225d06
...
26661cbfd8
@ -196,17 +196,10 @@ class CharGrid {
|
|||||||
fun matchRelative(c: Int, r: Int, relposes: Iterable<RelPos>, predicate: (char: Char) -> Boolean): List<RelPos> =
|
fun matchRelative(c: Int, r: Int, relposes: Iterable<RelPos>, predicate: (char: Char) -> Boolean): List<RelPos> =
|
||||||
relposes.filter { predicate(get(c + it.dc, r + it.dr)) }
|
relposes.filter { predicate(get(c + it.dc, r + it.dr)) }
|
||||||
|
|
||||||
fun marchMatching(pos: RelPos, relposes: Iterable<RelPos>, predicate: (char: Char) -> Boolean): List<RelPos> =
|
|
||||||
relposes.map { pos.translate(it) }.filter { predicate(get(it)) }
|
|
||||||
|
|
||||||
fun findMatches(predicate: (char: Char) -> Boolean): List<Pair<Int, Int>> {
|
fun findMatches(predicate: (char: Char) -> Boolean): List<Pair<Int, Int>> {
|
||||||
return generateGridPos().filter { predicate(get(it)) }.map { it.dc to it.dr }.toList()
|
return generateGridPos().filter { predicate(get(it)) }.map { it.dc to it.dr }.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findMatchesRelPos(predicate: (char: Char) -> Boolean): List<RelPos> {
|
|
||||||
return generateGridPos().filter { predicate(get(it)) }.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun collectMatches(predicate: (char: Char) -> Boolean): List<Pair<Char, RelPos>> {
|
fun collectMatches(predicate: (char: Char) -> Boolean): List<Pair<Char, RelPos>> {
|
||||||
return generateGridPos().filter { predicate(get(it)) }.map { get(it) to it }.toList()
|
return generateGridPos().filter { predicate(get(it)) }.map { get(it) to it }.toList()
|
||||||
}
|
}
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
package aoc2024
|
|
||||||
|
|
||||||
import println
|
|
||||||
import readInput
|
|
||||||
|
|
||||||
/*
|
|
||||||
--- Day 9: Disk Fragmenter ---
|
|
||||||
https://adventofcode.com/2024/day/9
|
|
||||||
*/
|
|
||||||
fun main() {
|
|
||||||
|
|
||||||
val inlineTestInput = """2333133121414131402"""
|
|
||||||
|
|
||||||
fun part1(input: List<String>): Long {
|
|
||||||
val diskSize = input[0].sumOf { it - '0' }
|
|
||||||
val bitmap = IntArray(diskSize) { -1 }
|
|
||||||
var pos = 0
|
|
||||||
var isFile = true
|
|
||||||
var fileId = 0
|
|
||||||
var usedBlocks = 0
|
|
||||||
for (c in input[0]) {
|
|
||||||
val size = c - '0'
|
|
||||||
if (isFile) {
|
|
||||||
usedBlocks += size
|
|
||||||
for (p in 1..size) {
|
|
||||||
bitmap[pos++] = fileId
|
|
||||||
}
|
|
||||||
fileId++
|
|
||||||
} else {
|
|
||||||
pos += size
|
|
||||||
}
|
|
||||||
isFile = !isFile
|
|
||||||
}
|
|
||||||
var backPos = diskSize - 1
|
|
||||||
for (i in 0 until usedBlocks) {
|
|
||||||
if (bitmap[i] == -1) {
|
|
||||||
while (bitmap[backPos] < 0) {
|
|
||||||
backPos--
|
|
||||||
}
|
|
||||||
bitmap[i] = bitmap[backPos]
|
|
||||||
bitmap[backPos--] = -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bitmap.take(usedBlocks).map(Int::toLong).reduceIndexed { index, acc, i -> acc + index * i }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun part2(input: List<String>): Long {
|
|
||||||
val diskSize = input[0].sumOf { it - '0' }
|
|
||||||
val bitmap = IntArray(diskSize) { 0 }
|
|
||||||
var pos = 0
|
|
||||||
var isFile = true
|
|
||||||
var fileId = 0
|
|
||||||
val freeList = HashMap<Int, MutableList<Int>>()
|
|
||||||
val fileList = ArrayList<Pair<Int, Pair<Int, Int>>>()
|
|
||||||
val newFileList = ArrayList<Pair<Int, Pair<Int, Int>>>()
|
|
||||||
for (c in input[0]) {
|
|
||||||
val size = c - '0'
|
|
||||||
if (isFile) {
|
|
||||||
if (size == 0) println("Narf!")
|
|
||||||
fileList.add(fileId to (pos to size))
|
|
||||||
fileId++
|
|
||||||
} else {
|
|
||||||
if (size > 0) {
|
|
||||||
freeList.getOrPut(size) { ArrayDeque(0) }.add(pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pos += size
|
|
||||||
isFile = !isFile
|
|
||||||
}
|
|
||||||
|
|
||||||
for (file in fileList.reversed()) {
|
|
||||||
val (filePos, size) = file.second
|
|
||||||
var bestList: MutableList<Int>? = null
|
|
||||||
var bestListSize = 0
|
|
||||||
for (s in size..9) {
|
|
||||||
val list = freeList[s]
|
|
||||||
if (list?.isNotEmpty() == true && list[0] < filePos) {
|
|
||||||
if (bestList == null || list[0] < bestList[0]) {
|
|
||||||
bestList = list
|
|
||||||
bestListSize = s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bestList != null) {
|
|
||||||
val newPos = bestList.removeAt(0)
|
|
||||||
if (bestListSize > size) {
|
|
||||||
val remBucket = freeList.getOrPut(bestListSize - size) { ArrayDeque(0) }
|
|
||||||
remBucket.add(newPos + size)
|
|
||||||
remBucket.sort()
|
|
||||||
}
|
|
||||||
newFileList.add(file.first to (newPos to size))
|
|
||||||
} else {
|
|
||||||
newFileList.add(file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (file in newFileList) {
|
|
||||||
for (i in 0 until file.second.second) {
|
|
||||||
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:
|
|
||||||
val testInput = inlineTestInput.trim().reader().readLines()
|
|
||||||
//val testInput = readInput("aoc2024/Day09_test")
|
|
||||||
val testInputPart1Result = part1(testInput)
|
|
||||||
println("Part 1 Test: $testInputPart1Result")
|
|
||||||
val testInputPart2Result = part2(testInput)
|
|
||||||
println("Part 2 Test: $testInputPart2Result")
|
|
||||||
check(testInputPart1Result == 1928L)
|
|
||||||
check(testInputPart2Result == 2858L)
|
|
||||||
|
|
||||||
val input = readInput("aoc2024/Day09")
|
|
||||||
part1(input).println()
|
|
||||||
part2(input).println()
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
package aoc2024
|
|
||||||
|
|
||||||
import CharGrid
|
|
||||||
import RelPos
|
|
||||||
import println
|
|
||||||
import readInput
|
|
||||||
|
|
||||||
/*
|
|
||||||
--- Day 10: Hoof It ---
|
|
||||||
https://adventofcode.com/2024/day/10
|
|
||||||
*/
|
|
||||||
fun main() {
|
|
||||||
|
|
||||||
val inlineTestInput = """
|
|
||||||
89010123
|
|
||||||
78121874
|
|
||||||
87430965
|
|
||||||
96549874
|
|
||||||
45678903
|
|
||||||
32019012
|
|
||||||
01329801
|
|
||||||
10456732
|
|
||||||
"""
|
|
||||||
|
|
||||||
fun part1(input: List<String>): Int {
|
|
||||||
val grid = CharGrid(input)
|
|
||||||
val starts = grid.findMatchesRelPos { it == '0' }
|
|
||||||
var sum = 0
|
|
||||||
for (startPos in starts) {
|
|
||||||
var nodes = listOf(startPos)
|
|
||||||
for (c in '1'..'9') {
|
|
||||||
nodes = nodes.flatMap { grid.marchMatching(it, CharGrid.PLUS_POS) { char -> char == c } }.distinct()
|
|
||||||
if (nodes.isEmpty()) break
|
|
||||||
}
|
|
||||||
sum += nodes.size
|
|
||||||
}
|
|
||||||
|
|
||||||
return sum
|
|
||||||
}
|
|
||||||
|
|
||||||
fun walkTrail(grid: CharGrid, c: Char, p: RelPos): Int {
|
|
||||||
val newNodes = grid.marchMatching(p, CharGrid.PLUS_POS) { it == c }
|
|
||||||
return if (c == '9') newNodes.size else newNodes.sumOf { walkTrail(grid, c + 1, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun part2(input: List<String>): Int {
|
|
||||||
val grid = CharGrid(input)
|
|
||||||
return grid.findMatchesRelPos { it == '0' }.sumOf { walkTrail(grid, '1', it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// test if implementation meets criteria from the description, like:
|
|
||||||
val testInput = inlineTestInput.trim().reader().readLines()
|
|
||||||
//val testInput = readInput("aoc2024/Day10_test")
|
|
||||||
val testInputPart1Result = part1(testInput)
|
|
||||||
println("Part 1 Test: $testInputPart1Result")
|
|
||||||
val testInputPart2Result = part2(testInput)
|
|
||||||
println("Part 2 Test: $testInputPart2Result")
|
|
||||||
check(testInputPart1Result == 36)
|
|
||||||
check(testInputPart2Result == 81)
|
|
||||||
|
|
||||||
val input = readInput("aoc2024/Day10")
|
|
||||||
part1(input).println()
|
|
||||||
part2(input).println()
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user