summaryrefslogtreecommitdiff
path: root/05/main.py
blob: c947ab7d444f528f7b04d495d2a05774d1b06884 (plain)
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