You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
5.7 KiB

from multiprocessing import Pool
lines = open('inputs/day5.txt').readlines()
def parsed_seeds(lines: list[str]) -> list[int]:
seeds = [int(x) for x in lines[0].strip("\n")[6:].split()]
return seeds
def parsed_maps(lines: list[str]) -> dict:
maps = {}
curr = ""
for i in range(2, len(lines)):
if lines[i] == "\n":
continue
elif lines[i] == "seed-to-soil map:\n":
maps[lines[i].split()[0]] = []
curr = lines[i].split()[0]
elif lines[i] == "soil-to-fertilizer map:\n":
maps[lines[i].split()[0]] = []
curr = lines[i].split()[0]
elif lines[i] == "fertilizer-to-water map:\n":
maps[lines[i].split()[0]] = []
curr = lines[i].split()[0]
elif lines[i] == "water-to-light map:\n":
maps[lines[i].split()[0]] = []
curr = lines[i].split()[0]
elif lines[i] == "light-to-temperature map:\n":
maps[lines[i].split()[0]] = []
curr = lines[i].split()[0]
elif lines[i] == "temperature-to-humidity map:\n":
maps[lines[i].split()[0]] = []
curr = lines[i].split()[0]
elif lines[i] == "humidity-to-location map:\n":
maps[lines[i].split()[0]] = []
curr = lines[i].split()[0]
else:
maps[curr].append([int(x) for x in lines[i].strip("\n").split()])
return maps
def traverse(seed: int) -> int:
map_names = list(maps.keys())
for name in map_names:
map_applied = False
for l in maps[name]:
if not map_applied:
if seed in range(l[1],l[1]+l[2]):
seed = seed + l[0] - l[1]
map_applied = True
return seed
def seeds_to_locations(seeds: list[int], maps: dict) -> list[int]:
locations = []
with Pool(4) as p:
locations = p.map(traverse, seeds)
return locations
def parsed_seed_ranges(lines: list[str]) -> list[tuple]:
seeds = [int(x) for x in lines[0].strip("\n")[6:].split()]
seed_ranges = []
for i in range(0, len(seeds), 2):
seed_ranges.append((seeds[i], seeds[i] + seeds[i+1]))
return seed_ranges
def seed_is_valid(seed: int, seed_ranges: list[tuple]) -> bool:
for seed_range in seed_ranges:
if seed >= seed_range[0] and seed < seed_range[1]:
return True
return False
def rev_traverse(loc: int) -> int:
map_names = list(maps.keys()).reverse()
for name in map_names:
map_applied = False
for l in maps[name]:
if not map_applied:
if seed in range(l[0],l[0]+l[2]):
seed = seed - l[0] + l[1]
map_applied = True
return seed
maps = parsed_maps(lines)
seeds = parsed_seeds(lines)
seed_ranges = parsed_seed_ranges(lines)
print(f"Solution Part 1: {min(seeds_to_locations(seeds, maps))}")
print(f"Solution Part 2: {min(min_loc_ranges)}")
""" yikes
def parsed_seed_ranges(lines: list[str]) -> list[tuple]:
seeds = [int(x) for x in lines[0].strip("\n")[6:].split()]
seed_ranges = []
for i in range(0, len(seeds), 2):
seed_ranges.append((seeds[i], seeds[i] + seeds[i+1]))
return seed_ranges
def map_seed_range(seed_range: tuple, mapping: list[int]) -> tuple:
#returns transformed range for one map and remaining range(s) that were not affected
def apply_map(tup: tuple, mapping):
x = tup[0]
y = tup[1]
result = (x + l[0] - l[1], y + l[0] - l[1])
#print(f"mapped {tup, result}")
return result
mapped = []
remaining = seed_range
for l in mapping:
not_mapped = []
#print(f"l: {l}")
#print(f"source range from {l[1]} to {l[1] + l[2]}")
while len(remaining) > 0:
r = remaining.pop()
#print(f"-----r: {r}-----")
if r[0] == r[1]:
pass
#print("just delete, empty range")
else:
if r[1] <= l[1]:
#print("not mapped")
not_mapped.append(r)
elif r[0] >= l[1] + l[2]:
#print("not mapped")
not_mapped.append(r)
elif r[0] >= l[1] and r[1] <= l[1] + l[2]:
mapped.append(apply_map(r, l))
elif r[0] < l[1] and r[1] <= l[1] + l[2]:
mapped.append(apply_map((l[1], r[1]), l))
not_mapped.append((r[0], l[1]))
#print(f"remained: {(r[0], l[1])}")
elif r[0] >= l[1] and r[1] > l[1] + l[2]:
mapped.append(apply_map((r[0], l[1] + l[2]), l))
not_mapped.append((l[1] + l[2], r[1]))
#print(f"remained: {(l[1] + l[2], r[1])}")
elif r[0] < l[1] and r[1] > l[1] + l[2]:
not_mapped.append(apply_map((l[1], l[1] + l[2]), l))
remaining.append((r[0], l[1]))
#print(f"remained: {(r[0], l[1])}")
remaining.append((l[1] + l[2], r[1]))
#print(f"remained: {(l[1] + l[2], r[1])}")
#print(not_mapped)
remaining = list(set(not_mapped))
#print(f"remaining {remaining}")
return mapped + remaining
def seed_range_to_loc_ranges(seed_ranges: list[tuple], maps: dict) -> list[tuple]:
# single seed range going through maps
#print(seed_ranges)
map_names = list(maps.keys())
for name in map_names:
#print(f"apply {name}")
seed_ranges = map_seed_range(seed_ranges, maps[name])
#print(seed_ranges)
return seed_ranges
#loc_ranges = seed_range_to_loc_ranges(parsed_seed_ranges(lines), maps)
#min_loc_ranges = [x for x, y in loc_ranges]
"""