| load_input = helper.load_input | load_input = helper.load_input | ||||
| debug = helper.debug | debug = helper.debug | ||||
| # FUTURE ME: HERE'S THE KEY | |||||
| # You don't have to check every seed. | |||||
| # Instead, create ranges, and use the later steps to cut those ranges | |||||
| # into chunks. The smallest value in the smallest chunk after the last | |||||
| # step is the solution. The brute-force solution takes an enormous amount | |||||
| # of time; the chunk solution is still polynomial time, I think, but | |||||
| # the n is much smaller (dozens rather than hundreds of millions). | |||||
| def within(target, start, end): | def within(target, start, end): | ||||
| if start == end: | if start == end: | ||||
| return target == start | return target == start | ||||
| start, end = end, start | start, end = end, start | ||||
| return target >= start and end >= target | return target >= start and end >= target | ||||
| def chunk_it(old_range, new_range): | |||||
| o_start, o_end = old_range | |||||
| n_start, n_end = new_range | |||||
| debug(o_start, o_end, n_start, n_end) | |||||
| # The new range is entirely outside the current range | |||||
| if n_end < o_start or n_start > o_end: | |||||
| debug("Entirely outside!") | |||||
| return sorted([old_range, new_range], key=lambda n:n[0]) | |||||
| # The new range is entirely within the current range | |||||
| if n_start >= o_start and n_end <= o_end: | |||||
| # We've already accounted for this range | |||||
| debug("Already got it") | |||||
| return [old_range] | |||||
| # The new range starts lower and ends higher | |||||
| if n_start <= o_start and n_end >= o_end: | |||||
| # We can replace the old range with the new one | |||||
| debug("Replacement!") | |||||
| return [new_range] | |||||
| # The new range starts lower but ends within | |||||
| if n_start <= o_start and n_end >= o_start and n_end <= o_end: | |||||
| debug("Starts before") | |||||
| return [[n_start, o_end]] | |||||
| # The new range starts within but ends higher | |||||
| if n_end >= o_end and n_start >= o_start and n_start <= o_end: | |||||
| debug("Ends after") | |||||
| return [[o_start, n_end]] | |||||
| raise Exception(f"What? What? Nothing matched: {old_range}, {new_range}") | |||||
| def main(): | def main(): | ||||
| lines = load_input(5) | lines = load_input(5) | ||||
| } | } | ||||
| maps_keys = list(maps_dict.keys()) | maps_keys = list(maps_dict.keys()) | ||||
| maps_dict["seeds"] = [int(n) for n in lines[0].split()[1:]] | maps_dict["seeds"] = [int(n) for n in lines[0].split()[1:]] | ||||
| debug(f"Starting with {len(maps_dict['seeds'])//2} ranges") | |||||
| real_seeds = [] | real_seeds = [] | ||||
| i, j = 0, 1 | i, j = 0, 1 | ||||
| while j < len(maps_dict["seeds"]): | while j < len(maps_dict["seeds"]): | ||||
| real_seeds.append((maps_dict["seeds"][i], maps_dict["seeds"][i] + maps_dict["seeds"][j])) | |||||
| new_range = [maps_dict["seeds"][i], maps_dict["seeds"][i] + maps_dict["seeds"][j]] | |||||
| if len(real_seeds) == 0: | |||||
| real_seeds.append(new_range) | |||||
| else: | |||||
| new_real_seeds = [] | |||||
| for range in real_seeds: | |||||
| add_ranges = chunk_it(range, new_range) | |||||
| debug(add_ranges) | |||||
| for r in add_ranges: | |||||
| if r not in new_real_seeds: | |||||
| new_real_seeds.append(r) | |||||
| real_seeds = list(new_real_seeds) | |||||
| i += 2 | |||||
| j += 2 | |||||
| debug(real_seeds, i, j) | |||||
| debug(f"Found {len(real_seeds)} actual ranges") | |||||
| real_seeds.sort(key=lambda n: n[0]) | |||||
| # debug(real_seeds) | |||||
| return | |||||
| # new_start = maps_dict["seeds"][i] | # new_start = maps_dict["seeds"][i] | ||||
| # new_end = new_start + maps_dict["seeds"][j] | # new_end = new_start + maps_dict["seeds"][j] | ||||
| # debug(f"Adding seeds in range {new_start}-{new_end}") | # debug(f"Adding seeds in range {new_start}-{new_end}") | ||||
| # debug(new_seeds) | # debug(new_seeds) | ||||
| # real_seeds.append(new_seeds) | # real_seeds.append(new_seeds) | ||||
| # debug(real_seeds) | # debug(real_seeds) | ||||
| i += 2 | |||||
| j += 2 | |||||
| seeds_list = [{"seed": seed[1]} for seed in real_seeds] | seeds_list = [{"seed": seed[1]} for seed in real_seeds] | ||||
| current_key = "" | current_key = "" |