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)}")