1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
#!/bin/python3
import sys
import re
# i want to throw up
numbers = [int(x) for x in input().split(":")[1].split()]
seed_ranges = []
for x in range(0, len(numbers), 2):
seed_ranges.append((numbers[x], numbers[x] + numbers[x+1],))
STEPS = [
'seed',
'soil',
'fertilizer',
'water',
'light',
'temperature',
'humidity',
'location',
]
maps = []
current_map = {"from": "", "to": ""}
for line in sys.stdin:
line = line.strip()
if len(line) == 0: continue
if "map:" in line:
current_map["from"], current_map["to"] = line.split()[0].split("-to-")
else:
dest_start, source_start, range_len = [int(x) for x in line.split()]
current_map["src_range"] = (source_start, source_start + range_len,)
current_map["dest_range"] = (dest_start, dest_start + range_len,)
current_map["offset"] = dest_start - source_start
current_map["length"] = range_len
maps.append(dict(current_map))
output_ranges = []
for inital_range in seed_ranges:
ranges = [inital_range]
# print(f"------ NEXT INPUT RANGE SET: {ranges} -------")
for step in STEPS[:-1]:
# print(f"[{step}] {len(ranges)} input ranges: {ranges}")
current_step_maps = [m for m in maps if m["from"] == step]
# print(f"current_step_maps\n\t" + '\n\t'.join([str(d) for d in current_step_maps]))
next_ranges = set()
for range in ranges:
applicable_maps = [m for m in current_step_maps if \
m["src_range"][0] <= range[0] < m["src_range"][1] or \
m["src_range"][0] < range[1] <= m["src_range"][1]]
applicable_maps = sorted(applicable_maps, key=lambda d: d["src_range"][0])
index = range[0]
# print(f"map range {range} using maps\n\t" + '\n\t'.join([str(d) for d in applicable_maps]))
while index < range[1]:
cover_step = 0
offset = 0
if len(applicable_maps) == 0:
# print("> no more maps ahead!")
cover_step = range[1] - index
offset = 0
else:
next_map = applicable_maps[0]
if next_map["src_range"][0] <= index < next_map["src_range"][1]:
# print(f"> {index} in map range")
cover_step = next_map["src_range"][1] - index
offset = next_map["offset"]
applicable_maps.pop(0)
else:
# print("> skipping until next map")
cover_step = next_map["src_range"][0] - index
offset = 0
cover_step = min(cover_step, range[1] - index)
next_ranges.add((index + offset, index + cover_step + offset,))
# print(f" creating a range with length {cover_step} and offset {offset}:")
# print(f" {(index, index + cover_step,)} -> {(index + offset, index + cover_step + offset,)}")
index += cover_step
# print(f"> end of input range reached")
# print("\n")
ranges = sorted(list(next_ranges), key=lambda t: t[0])
output_ranges += ranges
seed_ranges = sorted(seed_ranges, key=lambda t: t[0])
output_ranges = sorted(output_ranges, key=lambda t: t[0])
for range in seed_ranges:
intersections = [m for m in output_ranges if \
range[0] <= m[0] < range[1] or\
range[0] < m[1] <= range[1]]
if len(intersections) == 0: continue
intersections = [
(max(m[0], range[0]),
min(m[1], range[1]),) for m in intersections
]
intersections = sorted(intersections, key=lambda t: t[0])
print(f">> {intersections[0][0]}")
break
|