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] """