105 lines
2.9 KiB
Python
105 lines
2.9 KiB
Python
import sys
|
|
from collections import defaultdict
|
|
from dataclasses import dataclass
|
|
from typing import Literal, TypeAlias
|
|
|
|
MAP_ORDER = [
|
|
"seed",
|
|
"soil",
|
|
"fertilizer",
|
|
"water",
|
|
"light",
|
|
"temperature",
|
|
"humidity",
|
|
"location",
|
|
]
|
|
|
|
lines = sys.stdin.read().splitlines()
|
|
|
|
seeds: list[int] = []
|
|
maps: dict[tuple[str, str], list[tuple[int, int, int]]] = {}
|
|
|
|
# parsing
|
|
index = 2
|
|
while index < len(lines):
|
|
l0 = lines[index]
|
|
p1, _, p2 = l0.split("-")
|
|
p2 = p2.split()[0].strip()
|
|
|
|
index += 1
|
|
maps[p1, p2] = []
|
|
while index < len(lines) and lines[index]:
|
|
n1, n2, n3 = lines[index].split()
|
|
maps[p1, p2].append((int(n1), int(n2), int(n3)))
|
|
index += 1
|
|
|
|
index += 1
|
|
|
|
|
|
def find_location(seed: int) -> int:
|
|
value = seed
|
|
for map1, map2 in zip(MAP_ORDER[:-1], MAP_ORDER[1:]):
|
|
for target, start, length in maps[map1, map2]:
|
|
if value >= start and value < start + length:
|
|
value = target + (value - start)
|
|
break
|
|
return value
|
|
|
|
|
|
def find_range(
|
|
values: tuple[int, int], map: list[tuple[int, int, int]]
|
|
) -> list[tuple[int, int]]:
|
|
r_start, r_length = values
|
|
ranges: list[tuple[int, int]] = []
|
|
print(r_start, r_length)
|
|
for target, start, length in map:
|
|
# start is in the range
|
|
if start <= r_start and r_start < start + length:
|
|
if r_start + r_length < start + length:
|
|
ranges.append(
|
|
(target + r_start - start, r_length)
|
|
)
|
|
else:
|
|
ranges.append(
|
|
(target + r_start - start, length - (r_start - start))
|
|
)
|
|
elif start < r_start:
|
|
if r_start + r_length < start + length:
|
|
ranges.append(
|
|
(target + r_start - start, target + r_start - start + r_length)
|
|
)
|
|
elif start >= r_start and r_start >= start
|
|
|
|
if r_start <= start and start < start + length:
|
|
print(start, length, target)
|
|
if r_start + r_length < start + length:
|
|
ranges.append(
|
|
(target + (start - r_start), target + (start - r_start) + length)
|
|
)
|
|
else:
|
|
ranges.append((target + (start - r_start), target + length))
|
|
|
|
return ranges
|
|
|
|
|
|
# part 1
|
|
seeds = [int(s) for s in lines[0].split(":")[1].strip().split()]
|
|
answer_1 = min(find_location(seed) for seed in seeds)
|
|
print(f"answer 1 is {answer_1}")
|
|
|
|
# part 2
|
|
parts = lines[0].split(":")[1].strip().split()
|
|
seeds_p2 = [(int(s), int(e)) for s, e in zip(parts[::2], parts[1::2])]
|
|
|
|
for seed in range(seeds_p2[0][0], seeds_p2[0][0] + seeds_p2[0][1]):
|
|
print(seed, find_location(seed))
|
|
print("---")
|
|
|
|
seeds_p2 = [seeds_p2[0]]
|
|
for map1, map2 in zip(MAP_ORDER[:-1], MAP_ORDER[1:]):
|
|
seeds_p2 = [s2 for s1 in seeds_p2 for s2 in find_range(s1, maps[map1, map2])]
|
|
print(seeds_p2)
|
|
|
|
answer_2 = ...
|
|
print(f"answer 2 is {answer_2}")
|