def read_map(input): map = [] for line in input: if not line.strip(): break dst, src, count = nums(line) map.append((dst, src, count)) return map def overlap(a,b, x,y): """ if two ranges a..a+b and x..x+y overlap, returns the overlapping range""" if b <= x or y <= a: return (0,0) # no overlap return max(a,x), min(b,y) def lookup(map, m,n): r = [] used = [] for dst, src, count in map: a,b = overlap(m,m+n, src,src+count) if a != b: assert a < b used.append((a,b)) r.append((a-src+dst,b-a)) if not used: r.append((m,n)) else: used.sort() end = m+n for a,b in used: assert m <= a if m < a: r.append((m, a-m)) m = b if m < end: r.append((m,end-m)) return r def nums(s): return [int(x) for x in s.split()] def read_puzzle(input): l = next(input) name,_, data = l.partition(": ") assert name == 'seeds' seeds = nums(data) maps = {} for l in input: if l.strip(): assert ':' in l name = l.split()[0] frm, _, to = name.partition('-to-') assert frm assert to map = read_map(input) maps[(frm,to)] = map print(seeds) print(maps) locs = [] for i in range(0, len(seeds), 2): m,n = seeds[i:i+2] print(n, lookup(maps[('seed','soil')], m,n), seed2loc(maps, m,n)) locs.extend(seed2loc(maps, m,n)) print(min(locs)) def seed2loc(maps, m,n): r = [(m,n)] for a,b in [ ('seed', 'soil'), ('soil', 'fertilizer'), ('fertilizer', 'water'), ('water', 'light'), ('light', 'temperature'), ('temperature', 'humidity'), ('humidity', 'location'), ]: next = [] for m,n in r: s = lookup(maps[a,b], m,n) print(a,b,m,n,":", s) next.extend(s) r = next return r import sys read_puzzle(sys.stdin)