Files
advent-of-code-2023/05/puzzle.py
2023-12-12 11:00:44 -08:00

83 lines
2.4 KiB
Python

from itertools import count
from math import inf
from typing import Iterable, NamedTuple
class RangeConversion(NamedTuple):
destination_start: int
source_start: int
range_length: int
def resolve(self, source: int) -> int | None:
if self.source_start <= source < self.source_start + self.range_length:
return self.destination_start + source - self.source_start
return None
def reverse_resolve(self, destination: int) -> int | None:
if (
self.destination_start
<= destination
< self.destination_start + self.range_length
):
return self.source_start + destination - self.destination_start
return None
class SeedRange(NamedTuple):
start: int
length: int
def includes(self, seed: int):
return self.start <= seed < self.start + self.length
def resolve_destination(source: int, map: list[RangeConversion]) -> int:
for range_conversion in map:
if destination := range_conversion.resolve(source):
return destination
return source
def resolve_source(destination: int, map: list[RangeConversion]) -> int:
for range_conversion in map:
if source := range_conversion.reverse_resolve(destination):
return source
return destination
def solve_pt_1(seeds: list[int], maps: list[list[RangeConversion]]) -> int:
minimum_location = 9_999_999_999_999
for seed in seeds:
result = seed
for map in maps:
result = resolve_destination(result, map)
minimum_location = min(minimum_location, result)
return minimum_location
def solve_pt_2(seeds: list[int], maps: list[list[RangeConversion]]) -> int:
seed_ranges = [
SeedRange(start, length) for start, length in zip(seeds[::2], seeds[1::2])
]
for location in count():
if location % 100_000 == 0:
print(
f"Part 2 - [checking {location:,} through {location + 99_999:,}]",
end="\r",
)
result = location
for map in reversed(maps):
result = resolve_source(result, map)
seed_candidate = result
for map in maps:
result = resolve_destination(result, map)
for seed_range in seed_ranges:
if seed_range.includes(seed_candidate):
return location
raise NotImplementedError()