230 lines
6 KiB
Python
230 lines
6 KiB
Python
from dataclasses import dataclass
|
|
|
|
@dataclass
|
|
class Range:
|
|
start: int # Inclusive
|
|
end: int # Inclusive
|
|
|
|
@dataclass
|
|
class Remap:
|
|
dest_start: int = 0 # Inclusive
|
|
dest_end: int = 0 # Inclusive
|
|
src_start: int = 0 # Inclusive
|
|
src_end: int = 0 # Inclusive
|
|
|
|
|
|
def draw_ranges(ranges: list[Range]):
|
|
return
|
|
lol = [' '] * 100
|
|
for range_ in ranges:
|
|
for i in range(range_.start, range_.end + 1):
|
|
lol[i] = '#'
|
|
s_lol = ''.join(lol)
|
|
print(f'[{s_lol}]')
|
|
|
|
def draw_remap(remap: Remap, chr):
|
|
return
|
|
src_lol = [' '] * 100
|
|
dst_lol = [' '] * 100
|
|
|
|
src_lol[remap.src_start] = '['
|
|
src_lol[remap.src_end] = ']'
|
|
for j in range(remap.src_start, remap.src_end + 1):
|
|
src_lol[j] = chr
|
|
dst_lol[remap.dest_start] = '['
|
|
dst_lol[remap.dest_end] = ']'
|
|
for j in range(remap.dest_start, remap.dest_end + 1):
|
|
dst_lol[j] = chr
|
|
|
|
s_lol = ''.join(src_lol)
|
|
print(f'[{s_lol}]')
|
|
s_lol = ''.join(dst_lol)
|
|
print(f'[{s_lol}]')
|
|
|
|
def draw_remaps(remaps: list[Remap]):
|
|
return
|
|
src_lol = [' '] * 100
|
|
dst_lol = [' '] * 100
|
|
|
|
for i, remap in enumerate(remaps):
|
|
src_lol[remap.src_start] = '['
|
|
src_lol[remap.src_end] = ']'
|
|
for j in range(remap.src_start, remap.src_end + 1):
|
|
src_lol[j] = str(i)
|
|
dst_lol[remap.dest_start] = '['
|
|
dst_lol[remap.dest_end] = ']'
|
|
for j in range(remap.dest_start, remap.dest_end + 1):
|
|
dst_lol[j] = str(i)
|
|
|
|
s_lol = ''.join(src_lol)
|
|
print(f'[{s_lol}]')
|
|
s_lol = ''.join(dst_lol)
|
|
print(f'[{s_lol}]')
|
|
|
|
|
|
|
|
def remap_range(map: list[Remap], initial_range: Range):
|
|
unchopped: list[Range] = [initial_range]
|
|
chopped: list[Range] = []
|
|
|
|
for i, remap in enumerate(map):
|
|
print('We do remap now')
|
|
draw_remap(remap, str(i))
|
|
|
|
new_ranges: list[Range] = []
|
|
for range_ in unchopped:
|
|
# This remap does not apply to us, just move along
|
|
if not(range_.start <= remap.src_end and remap.src_start <= range_.end):
|
|
new_ranges.append(range_)
|
|
continue
|
|
|
|
# Case 1:
|
|
# #######
|
|
# [ ]
|
|
# ###
|
|
if range_.start < remap.src_start:
|
|
new_ranges.append(Range(start=range_.start, end=remap.src_start - 1))
|
|
print('Case 1')
|
|
draw_ranges(new_ranges)
|
|
|
|
# Case 2:
|
|
# ####
|
|
# [ ]
|
|
# ####
|
|
# Actually do remap and append to chopped list
|
|
bump = remap.dest_start - remap.src_start
|
|
chopped.append(Range(max(range_.start, remap.src_start) + bump, min(range_.end, remap.src_end) + bump))
|
|
print('Case 2')
|
|
draw_ranges(chopped)
|
|
|
|
# Case 2:
|
|
# ######
|
|
# [ ]
|
|
# ##
|
|
if range_.end > remap.src_end:
|
|
new_ranges.append(Range(start=remap.src_end + 1, end=range_.end))
|
|
print('Case 3')
|
|
draw_ranges(new_ranges)
|
|
|
|
print('New ranges are')
|
|
draw_ranges(new_ranges)
|
|
unchopped = new_ranges.copy()
|
|
|
|
return unchopped + chopped
|
|
|
|
|
|
def read_map(lines, i):
|
|
remaps: list[Remap] = []
|
|
while i < len(lines) and lines[i] != '':
|
|
s_dest_start, s_src_start, s_length = lines[i].split(' ')
|
|
length = int(s_length)
|
|
|
|
remap = Remap()
|
|
remap.dest_start = int(s_dest_start)
|
|
remap.src_start = int(s_src_start)
|
|
|
|
remap.dest_end = remap.dest_start + length - 1
|
|
remap.src_end = remap.src_start + length - 1
|
|
|
|
remaps.append(remap)
|
|
|
|
i += 1
|
|
|
|
return remaps, i
|
|
|
|
|
|
def do_thing(n_from: str, n_to: str, in_ranges: list[Range], map: list[Remap]) -> list[Range]:
|
|
print(f'{n_from} to {n_to}')
|
|
draw_ranges(in_ranges)
|
|
draw_remaps(map)
|
|
print('---')
|
|
out_ranges = []
|
|
for seed in in_ranges:
|
|
draw_ranges([seed])
|
|
remapped = remap_range(map, seed)
|
|
out_ranges += remapped
|
|
draw_ranges(remapped)
|
|
print()
|
|
print('---')
|
|
|
|
return out_ranges
|
|
|
|
|
|
def get_data():
|
|
with open('input.txt', 'r') as f:
|
|
lines = f.readlines()
|
|
lines = [line.strip('\n') for line in lines]
|
|
|
|
seeds: list[Range] = []
|
|
s_seeds = lines[0].split(' ')[1:]
|
|
|
|
for i in range(len(s_seeds) // 2):
|
|
start = int(s_seeds[i * 2 + 0])
|
|
length = int(s_seeds[i * 2 + 1])
|
|
end = start + length - 1
|
|
|
|
seeds.append(Range(start=start, end=end))
|
|
|
|
print(seeds)
|
|
|
|
idx = 3
|
|
seed_to_soil, idx = read_map(lines, idx)
|
|
print(seed_to_soil, idx)
|
|
|
|
idx += 2
|
|
soil_to_fertilizer, idx = read_map(lines, idx)
|
|
print(soil_to_fertilizer, idx)
|
|
|
|
idx += 2
|
|
fertilizer_to_water, idx = read_map(lines, idx)
|
|
print(fertilizer_to_water, idx)
|
|
|
|
idx += 2
|
|
water_to_light, idx = read_map(lines, idx)
|
|
print(water_to_light, idx)
|
|
|
|
idx += 2
|
|
light_to_temperature, idx = read_map(lines, idx)
|
|
print(light_to_temperature, idx)
|
|
|
|
idx += 2
|
|
temperature_to_humidity, idx = read_map(lines, idx)
|
|
print(temperature_to_humidity, idx)
|
|
|
|
idx += 2
|
|
humidity_to_location, idx = read_map(lines, idx)
|
|
print(humidity_to_location, idx)
|
|
|
|
|
|
soils = do_thing('Seed', 'Soil', seeds, seed_to_soil)
|
|
print()
|
|
|
|
fetilizers = do_thing('Soil', 'Fertilizer', soils, soil_to_fertilizer)
|
|
print()
|
|
|
|
waters = do_thing('Fertilizer', 'Water', fetilizers, fertilizer_to_water)
|
|
print()
|
|
|
|
lights = do_thing('Water', 'Light', waters, water_to_light)
|
|
print()
|
|
|
|
print(lights, light_to_temperature)
|
|
temperatures = do_thing('Light', 'Temperatures', lights, light_to_temperature)
|
|
print()
|
|
|
|
humidities = do_thing('Temperatures', 'Humidity', temperatures, temperature_to_humidity)
|
|
print()
|
|
|
|
locations = do_thing('Humidity', 'Location', humidities, humidity_to_location)
|
|
print()
|
|
|
|
print(locations)
|
|
lowest = locations[0].start
|
|
for loc in locations:
|
|
lowest = min(lowest, loc.start)
|
|
|
|
print(lowest)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
get_data()
|