164 lines
4.7 KiB
Python
164 lines
4.7 KiB
Python
EXAMPLE = """
|
|
seeds: 79 14 55 13
|
|
|
|
seed-to-soil map:
|
|
50 98 2
|
|
52 50 48
|
|
|
|
soil-to-fertilizer map:
|
|
0 15 37
|
|
37 52 2
|
|
39 0 15
|
|
|
|
fertilizer-to-water map:
|
|
49 53 8
|
|
0 11 42
|
|
42 0 7
|
|
57 7 4
|
|
|
|
water-to-light map:
|
|
88 18 7
|
|
18 25 70
|
|
|
|
light-to-temperature map:
|
|
45 77 23
|
|
81 45 19
|
|
68 64 13
|
|
|
|
temperature-to-humidity map:
|
|
0 69 1
|
|
1 0 69
|
|
|
|
humidity-to-location map:
|
|
60 56 37
|
|
56 93 4
|
|
"""
|
|
|
|
def clean(text: str) -> list[str]:
|
|
return list(text.splitlines())
|
|
|
|
def solve(lines: list[str]):
|
|
seeds = []
|
|
idx = -1
|
|
maps = []
|
|
|
|
for (_, line) in enumerate(lines):
|
|
if line.startswith("seeds:"):
|
|
seeds = map(int, line.replace("seeds:", "").strip().split(" "))
|
|
continue
|
|
if line.strip() == "":
|
|
continue
|
|
if "map" in line:
|
|
maps.append([])
|
|
idx += 1
|
|
continue
|
|
else:
|
|
maps[idx].append(list(map(int, line.split(" "))))
|
|
|
|
locs = []
|
|
for current in seeds:
|
|
for m in maps:
|
|
for mapping in m:
|
|
dest_range_start, source_range_start, range_len = mapping
|
|
if current >= source_range_start and current < source_range_start + range_len:
|
|
current = dest_range_start + (current - source_range_start)
|
|
break
|
|
else:
|
|
current = current
|
|
locs.append(current)
|
|
return min(locs)
|
|
|
|
def solve2(lines: list[str]):
|
|
seeds = []
|
|
idx = -1
|
|
maps = []
|
|
|
|
for (_, line) in enumerate(lines):
|
|
if line.startswith("seeds:"):
|
|
all_seeds = []
|
|
seeds = list(map(int, line.replace("seeds:", "").strip().split(" ")))
|
|
for i in range(0, len(seeds), 2):
|
|
all_seeds.append(seeds[i:i+2])
|
|
seeds = all_seeds
|
|
continue
|
|
if line.strip() == "":
|
|
continue
|
|
if "map" in line:
|
|
maps.append([])
|
|
idx += 1
|
|
continue
|
|
else:
|
|
maps[idx].append(list(map(int, line.split(" "))))
|
|
|
|
# source: |---------------------|
|
|
# seeds:
|
|
# |---|
|
|
# aaaaaabbbb
|
|
# aaaaaabbbbbbbbbbbbbbbbbbbbbbcccc
|
|
# aaaaaaaaaaaaaaaa
|
|
# aaaaaaaaaaaaaaaaaaaccccc
|
|
# |-------|
|
|
|
|
for m in maps:
|
|
next_seeds = []
|
|
while seeds:
|
|
seed_start, seed_range = seeds.pop()
|
|
seed_end = seed_start + seed_range
|
|
for mapping in m:
|
|
dest_start, source_start, m_range = mapping
|
|
source_end = source_start + m_range
|
|
|
|
if seed_end <= source_start:
|
|
continue
|
|
elif seed_start < source_start and seed_end <= source_end:
|
|
a_range = source_start - seed_start
|
|
seeds.append([seed_start, a_range])
|
|
b_range = seed_end - source_start
|
|
next_seeds.append([dest_start, b_range])
|
|
break
|
|
elif seed_start < source_start and seed_end > source_end:
|
|
a_range = source_start - seed_start
|
|
seeds.append([seed_start, a_range])
|
|
next_seeds.append([dest_start, m_range]) # b range
|
|
c_range = seed_end - source_end
|
|
next_seeds.append([source_end, c_range])
|
|
break
|
|
elif seed_start >= source_start and seed_end <= source_end:
|
|
new_seed_start = dest_start + (seed_start - source_start)
|
|
next_seeds.append([new_seed_start, seed_range])
|
|
break
|
|
elif seed_start >= source_start and seed_start < source_end:
|
|
new_seed_start = dest_start + (seed_start - source_start)
|
|
a_range = source_end - seed_start
|
|
next_seeds.append([new_seed_start, a_range])
|
|
c_range = seed_end - source_end
|
|
seeds.append([source_end, c_range])
|
|
break
|
|
elif seed_start >= source_end:
|
|
continue
|
|
else:
|
|
print(f"{seed_start=} {seed_range=} {seed_end=}")
|
|
print(f"{source_start=} {source_end=}")
|
|
raise Exception("Unexpected case")
|
|
else:
|
|
next_seeds.append([seed_start, seed_range])
|
|
seeds = next_seeds
|
|
return min(seeds)[0]
|
|
|
|
def main():
|
|
example = clean(EXAMPLE)
|
|
print("Example 1:", solve(example))
|
|
|
|
data = clean(open("i5.txt").read())
|
|
print("Solution 1:", solve(data))
|
|
|
|
example = clean(EXAMPLE)
|
|
print("Example 2:", solve2(example))
|
|
|
|
data = clean(open("i5.txt").read())
|
|
print("Solution 2:", solve2(data))
|
|
assert(solve2(data) == 63179500)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|