day5: Fix integer overflow bug
This commit is contained in:
parent
713bc2b47d
commit
13454b3f18
62
day5/day5.kt
62
day5/day5.kt
|
@ -1,6 +1,6 @@
|
|||
import java.io.File
|
||||
|
||||
typealias Map = Pair<UIntRange, UIntRange>
|
||||
typealias Map = Pair<LongRange, LongRange>
|
||||
|
||||
fun main() {
|
||||
val input = File("input")
|
||||
|
@ -13,11 +13,11 @@ fun main() {
|
|||
println(part2(seedRanges, maps))
|
||||
}
|
||||
|
||||
fun part1(seeds: List<UInt>, maps: List<List<Map>>): UInt {
|
||||
fun part1(seeds: List<Long>, maps: List<List<Map>>): Long {
|
||||
return seeds.map { seed -> maps.fold(seed) { toFind, map -> findMapping(toFind, map) } }.min()
|
||||
}
|
||||
|
||||
fun findMapping(toFind: UInt, maps: List<Map>): UInt {
|
||||
fun findMapping(toFind: Long, maps: List<Map>): Long {
|
||||
for (map in maps) {
|
||||
if (toFind >= map.first.first && toFind <= map.first.last) {
|
||||
val index = toFind - map.first.first
|
||||
|
@ -34,50 +34,24 @@ fun findMapping(toFind: UInt, maps: List<Map>): UInt {
|
|||
return toFind
|
||||
}
|
||||
|
||||
fun part2(seedRanges: List<UIntRange>, maps: List<List<Map>>): UInt {
|
||||
fun part2(seedRanges: List<LongRange>, maps: List<List<Map>>): Long {
|
||||
return seedRanges
|
||||
.map { range ->
|
||||
maps
|
||||
.fold(listOf(range)) { toReduce, map -> findReduction(toReduce, map) }
|
||||
.filter {
|
||||
// TODO(tlater): Remove this cursed filter
|
||||
//
|
||||
// Sometimes the source and range match up
|
||||
// perfectly, and the destination starts
|
||||
// with 0.
|
||||
//
|
||||
// Maybe this is a bug in the puzzle (?!),
|
||||
// or whenever this happens my logic
|
||||
// breaks down and the resulting
|
||||
// translated range always ends up in the
|
||||
// result.
|
||||
//
|
||||
// Nonetheless, filtering these 0s out
|
||||
// gives the right answer.
|
||||
//
|
||||
// More likely it's a booby trap for
|
||||
// *exactly* the logical fallacy I'm
|
||||
// committing?
|
||||
//
|
||||
// That, *or* it's just unlikely any one
|
||||
// range is the lowest in the end, and
|
||||
// these don't happen to contribute, while
|
||||
// the rest is computed correctly.
|
||||
it.first != 0u
|
||||
}
|
||||
.map { it.first }
|
||||
.min()
|
||||
}
|
||||
.min()
|
||||
}
|
||||
|
||||
fun findReduction(toReduce: List<UIntRange>, maps: List<Map>): List<UIntRange> {
|
||||
var result: MutableList<UIntRange> = mutableListOf()
|
||||
var reducing: MutableList<UIntRange> = mutableListOf()
|
||||
fun findReduction(toReduce: List<LongRange>, maps: List<Map>): List<LongRange> {
|
||||
var result: MutableList<LongRange> = mutableListOf()
|
||||
var reducing: MutableList<LongRange> = mutableListOf()
|
||||
reducing.addAll(toReduce)
|
||||
|
||||
for (map in maps) {
|
||||
var next: MutableList<UIntRange> = mutableListOf()
|
||||
var next: MutableList<LongRange> = mutableListOf()
|
||||
val source = map.first
|
||||
val destination = map.second
|
||||
|
||||
|
@ -96,17 +70,17 @@ fun findReduction(toReduce: List<UIntRange>, maps: List<Map>): List<UIntRange> {
|
|||
}
|
||||
|
||||
fun getDestinationForOverlap(
|
||||
overlap: UIntRange,
|
||||
source: UIntRange,
|
||||
destination: UIntRange
|
||||
): UIntRange {
|
||||
overlap: LongRange,
|
||||
source: LongRange,
|
||||
destination: LongRange
|
||||
): LongRange {
|
||||
val startDiff = overlap.first - source.first
|
||||
val endDiff = source.last - overlap.last
|
||||
|
||||
return destination.first + startDiff..destination.last - endDiff
|
||||
}
|
||||
|
||||
fun getOverlap(range1: UIntRange, range2: UIntRange): Pair<UIntRange?, List<UIntRange>> {
|
||||
fun getOverlap(range1: LongRange, range2: LongRange): Pair<LongRange?, List<LongRange>> {
|
||||
val start =
|
||||
when {
|
||||
range1.first <= range2.first -> range2.first
|
||||
|
@ -124,24 +98,24 @@ fun getOverlap(range1: UIntRange, range2: UIntRange): Pair<UIntRange?, List<UInt
|
|||
if (start > end) {
|
||||
return Pair(null, listOf(range1))
|
||||
} else {
|
||||
val excess: MutableList<UIntRange> = mutableListOf()
|
||||
val excess: MutableList<LongRange> = mutableListOf()
|
||||
|
||||
if (start > range1.first) {
|
||||
excess.add(range1.first ..< start)
|
||||
}
|
||||
|
||||
if (range1.last > end) {
|
||||
excess.add(end + 1u..range1.last)
|
||||
excess.add(end + 1L..range1.last)
|
||||
}
|
||||
|
||||
return Pair(start..end, excess)
|
||||
}
|
||||
}
|
||||
|
||||
fun parseInput(input: File): Pair<List<UInt>, List<List<Map>>> {
|
||||
fun parseInput(input: File): Pair<List<Long>, List<List<Map>>> {
|
||||
val text = input.bufferedReader()
|
||||
|
||||
val seeds = text.readLine().split(": ")[1].split(" ").map { it.toUInt() }
|
||||
val seeds = text.readLine().split(": ")[1].split(" ").map { it.toLong() }
|
||||
text.readLine()
|
||||
|
||||
var line = text.readLine()
|
||||
|
@ -152,7 +126,7 @@ fun parseInput(input: File): Pair<List<UInt>, List<List<Map>>> {
|
|||
line == "" -> Unit // Skip empty lines
|
||||
line.endsWith(':') -> maps.add(mutableListOf())
|
||||
else -> {
|
||||
val (destination, source, length) = line.split(" ").map { it.toUInt() }
|
||||
val (destination, source, length) = line.split(" ").map { it.toLong() }
|
||||
maps.last()
|
||||
.add(Pair(source ..< source + length, destination ..< destination + length))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue