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.
97 lines
3.2 KiB
97 lines
3.2 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())[::-1]
|
|
for name in map_names:
|
|
map_applied = False
|
|
for l in maps[name]:
|
|
if not map_applied:
|
|
if loc in range(l[0],l[0]+l[2]):
|
|
loc = loc - l[0] + l[1]
|
|
map_applied = True
|
|
return loc
|
|
|
|
|
|
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))}")
|
|
|
|
def find_lowest_valid_location(seed_ranges: list[tuple]) -> int:
|
|
for i in range(100000000):
|
|
seed = rev_traverse(i)
|
|
if seed_is_valid(seed, seed_ranges):
|
|
return i
|
|
return None
|
|
|
|
print(f"Solution to Part 2 takes a couple of minutes.")
|
|
print(f"Solution Part 2: {find_lowest_valid_location(seed_ranges)}")
|