Day 5 still gives headaches, so much off by one...

This commit is contained in:
Christoph Stahl 2023-12-06 10:04:44 +01:00
parent fda10274ee
commit 5f2143270d

120
day05.py
View file

@ -2,6 +2,7 @@ from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
from itertools import chain from itertools import chain
import bisect import bisect
from typing import Optional
import regex as re import regex as re
@ -13,35 +14,62 @@ class Map:
def __init__(self, group: list[str]) -> None: def __init__(self, group: list[str]) -> None:
self.maps = [] self.maps = []
for line in group[1:]: for line in group:
start_dest, start_source, id_range = [ start_dest, start_source, id_range = [
int(d) for d in re.findall(r"\d+", line) int(d) for d in re.findall(r"\d+", line)
] ]
bisect.insort(self.maps, (start_source, start_dest, id_range)) bisect.insort(self.maps, (start_source, start_dest - start_source, id_range))
zero_offsets = []
start = 0
for source, _, rnge in self.maps:
if source > start:
zero_offsets.append((start, 0, source - start))
start = source + rnge
for m in zero_offsets:
bisect.insort(self.maps, m)
def find_bucket(self, x: int) -> Optional[int]:
for idx, (source, offset, rnge) in enumerate(self.maps):
if x >= source and x < source + rnge:
return idx
return None
def __getitem__(self, x: int) -> int: def __getitem__(self, x: int) -> int:
print(f"In {x}") for (source, offset, rnge) in self.maps:
for (source, dest, rnge) in self.maps:
print(f"Source {source}")
if x >= source and x < source + rnge: if x >= source and x < source + rnge:
return dest + (x - source) return x + offset
return x return x
# index = bisect.bisect_left(self.maps, (x+1,0,0)) # index = bisect.bisect_left(self.maps, (x+1,0,0)) - 1
# index -= 1 # # index -= 1
# if index < 0: # # if index < 0:
# return x # # return x
# #
# source, dest, id_range = self.maps[index] # source, offset, id_range = self.maps[index]
# if x < source + id_range: # if x >= source + id_range:
# return dest + (x - source) # return x
# # if x < source + id_range:
# return x + offset
# return x # return x
#
def merge(self, other: Map) -> None:
newmappings = []
for osource, ooffset, orange in other.maps:
for ssource, soffset, srange in self.maps:
if osource >= ssource and osource <= ssource + srange:
pass
def __repr__(self) -> str: def __repr__(self) -> str:
l = [] l = []
for k, v, x in self.maps: for k, offset, x in self.maps:
l.append(f"{k} - {k + x}: {v} - {v + x}") l.append(f"{k} - {k + x - 1}: {k+offset} - {k+ offset + x - 1}")
return f"Map({', '.join(l)})" return f"Map({', '.join(l)})"
@ -55,9 +83,10 @@ class Problem:
output_value = value output_value = value
while target != cat_to: while target != cat_to:
new_target= list(filter(lambda fromto: fromto[0] == target, self.maps.keys()))[0][1] new_target= list(filter(lambda fromto: fromto[0] == target, self.maps.keys()))[0][1]
print(f"{target}({output_value})") # print(f"{target}({output_value})")
output_value = self.maps[(target, new_target)][output_value] output_value = self.maps[(target, new_target)][output_value]
print(f"{new_target}({output_value})") # print(f"{new_target}({output_value})")
# self.cache[(old_value, target)] = (output_value, new_target)
target = new_target target = new_target
return output_value return output_value
@ -94,23 +123,62 @@ class Day05(AocSameParser[Problem], Aoc2[Problem, Problem]):
return Problem.from_input(inpt) return Problem.from_input(inpt)
def part1(self, inpt: Problem) -> int: def part1(self, inpt: Problem) -> int:
return min(inpt.convert("seed", "location", x) for x in inpt.seeds) # print([inpt.maps["seed", "soil"][x] for x in range(100)])
#
# print(inpt.maps["soil", "fertilizer"])
# print(inpt.maps["soil", "fertilizer"][14])
# print([inpt.maps["soil", "fertilizer"][x] for x in range(100)])
return (min([inpt.convert("seed", "location", x) for x in inpt.seeds]))
def part2(self, inpt: Problem) -> int: def part2(self, inpt: Problem) -> int:
print(inpt.maps[("light", "temperature")]) order = [("seed", "soil"), ("soil", "fertilizer"), ("fertilizer", "water"), ("water", "light"), ("light", "temperature"), ("temperature", "humidity"), ("humidity", "location")]
print(inpt.convert("seed", "location", 82)) seed_iter = iter(inpt.seeds)
# seed_iter = iter(inpt.seeds) seeds = list(zip(seed_iter, seed_iter))
# seeds = [] for translation in order:
# for start, rnge in zip(seed_iter, seed_iter): print(translation)
# seeds.extend(range(start,start+rnge)) print(seeds)
# print([inpt.convert("seed", "location", x) for x in seeds]) new_to_convert = []
current_map = inpt.maps[translation]
# print(seeds[1])
# print(current_map)
for seed in seeds:
cur_range_start, cur_range_range = seed
cur_end = cur_range_start + cur_range_range
index = current_map.find_bucket(cur_range_start)
if index is not None:
# print(current_map.maps[index])
section_start, section_offset, section_range = current_map.maps[index]
section_end = section_start + section_range
if cur_end <= section_end:
new_to_convert.append((cur_range_start + section_offset, cur_range_range))
else:
# split
new_to_convert.append((cur_range_start + section_offset, section_end - cur_range_start))
if index == len(current_map.maps) - 1:
new_to_convert.append((section_end, cur_end - section_start))
else:
next_start, next_offset, next_range = current_map.maps[index + 1]
next_end = next_start + next_range
new_to_convert.append((section_end + next_offset, cur_end - section_start))
if cur_end > next_end:
print("Oh no")
else:
new_to_convert.append(seed)
seeds = new_to_convert
# return min(inpt.convert("seed", "location", x) for x in seeds)
def main(): def main():
day5 = Day05() day5 = Day05()
day5.run_example_2() print(day5.run_example_2())
if __name__ == "__main__": if __name__ == "__main__":