thomas_2023/day_5/part2.py

231 lines
6 KiB
Python
Raw Permalink Normal View History

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()