implemented day05... finally
This commit is contained in:
parent
0f3bcc7aa7
commit
418a537df6
1 changed files with 58 additions and 87 deletions
141
day05.py
141
day05.py
|
@ -1,6 +1,5 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from itertools import chain
|
|
||||||
import bisect
|
import bisect
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
@ -12,65 +11,42 @@ from aoc import Aoc2, AocSameParser
|
||||||
|
|
||||||
class Map:
|
class Map:
|
||||||
def __init__(self, group: list[str]) -> None:
|
def __init__(self, group: list[str]) -> None:
|
||||||
self.maps = []
|
self.maps: list[tuple[int, int, int]] = []
|
||||||
|
|
||||||
for line in group:
|
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 - start_source, id_range))
|
bisect.insort(
|
||||||
|
self.maps,
|
||||||
|
(start_source, start_dest - start_source, start_source + id_range - 1),
|
||||||
|
)
|
||||||
zero_offsets = []
|
zero_offsets = []
|
||||||
start = 0
|
start = 0
|
||||||
for source, _, rnge in self.maps:
|
for section_start, _, section_end in self.maps:
|
||||||
if source > start:
|
if section_start > start:
|
||||||
zero_offsets.append((start, 0, source - start))
|
zero_offsets.append((start, 0, start - 1))
|
||||||
start = source + rnge
|
start = section_end + 1
|
||||||
for m in zero_offsets:
|
for m in zero_offsets:
|
||||||
bisect.insort(self.maps, m)
|
bisect.insort(self.maps, m)
|
||||||
|
|
||||||
def find_bucket(self, x: int) -> Optional[int]:
|
def find_bucket(self, x: int) -> Optional[int]:
|
||||||
for idx, (source, offset, rnge) in enumerate(self.maps):
|
for idx, (source, _, end) in enumerate(self.maps):
|
||||||
if x >= source and x < source + rnge:
|
if source <= x <= end:
|
||||||
return idx
|
return idx
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def __getitem__(self, x: int) -> int:
|
def __getitem__(self, x: int) -> int:
|
||||||
for (source, offset, rnge) in self.maps:
|
for source, offset, end in self.maps:
|
||||||
if x >= source and x < source + rnge:
|
if source <= x <= end:
|
||||||
return x + offset
|
return x + offset
|
||||||
return x
|
return x
|
||||||
# index = bisect.bisect_left(self.maps, (x+1,0,0)) - 1
|
|
||||||
# # index -= 1
|
|
||||||
# # if index < 0:
|
|
||||||
# # return x
|
|
||||||
#
|
|
||||||
# source, offset, id_range = self.maps[index]
|
|
||||||
# if x >= source + id_range:
|
|
||||||
# return x
|
|
||||||
# # if x < source + id_range:
|
|
||||||
# return x + offset
|
|
||||||
# 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 = []
|
map_strs = []
|
||||||
for k, offset, x in self.maps:
|
for k, offset, end in self.maps:
|
||||||
l.append(f"{k} - {k + x - 1}: {k+offset} - {k+ offset + x - 1}")
|
map_strs.append(f"{k} - {end}: {k+offset} - {k+ offset + end}")
|
||||||
return f"Map({', '.join(l)})"
|
return f"Map({', '.join(map_strs)})"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -82,11 +58,10 @@ class Problem:
|
||||||
target = cat_from
|
target = cat_from
|
||||||
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(
|
||||||
# print(f"{target}({output_value})")
|
filter(lambda fromto: fromto[0] == target, self.maps.keys())
|
||||||
|
)[0][1]
|
||||||
output_value = self.maps[(target, new_target)][output_value]
|
output_value = self.maps[(target, 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
|
||||||
|
|
||||||
|
@ -97,6 +72,7 @@ class Problem:
|
||||||
raise RuntimeError(f'Could not parse "{line}" as group header')
|
raise RuntimeError(f'Could not parse "{line}" as group header')
|
||||||
|
|
||||||
return header_match["source"], header_match["dest"]
|
return header_match["source"], header_match["dest"]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_input(inpt: str) -> Problem:
|
def from_input(inpt: str) -> Problem:
|
||||||
lines = inpt.splitlines()
|
lines = inpt.splitlines()
|
||||||
|
@ -105,7 +81,7 @@ class Problem:
|
||||||
raise RuntimeError(f'Could not parse "{lines[0]}" as seed list')
|
raise RuntimeError(f'Could not parse "{lines[0]}" as seed list')
|
||||||
seeds = [int(s) for s in seed_match.captures("seedid")]
|
seeds = [int(s) for s in seed_match.captures("seedid")]
|
||||||
|
|
||||||
groups = []
|
groups: list[list[str]] = []
|
||||||
for line in lines[1:]:
|
for line in lines[1:]:
|
||||||
if not line:
|
if not line:
|
||||||
groups.append([])
|
groups.append([])
|
||||||
|
@ -123,62 +99,57 @@ 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:
|
||||||
# print([inpt.maps["seed", "soil"][x] for x in range(100)])
|
return min(inpt.convert("seed", "location", x) for x in inpt.seeds)
|
||||||
#
|
|
||||||
# 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:
|
||||||
order = [("seed", "soil"), ("soil", "fertilizer"), ("fertilizer", "water"), ("water", "light"), ("light", "temperature"), ("temperature", "humidity"), ("humidity", "location")]
|
order = [
|
||||||
|
("seed", "soil"),
|
||||||
|
("soil", "fertilizer"),
|
||||||
|
("fertilizer", "water"),
|
||||||
|
("water", "light"),
|
||||||
|
("light", "temperature"),
|
||||||
|
("temperature", "humidity"),
|
||||||
|
("humidity", "location"),
|
||||||
|
]
|
||||||
seed_iter = iter(inpt.seeds)
|
seed_iter = iter(inpt.seeds)
|
||||||
seeds = list(zip(seed_iter, seed_iter))
|
seeds = [
|
||||||
|
(start, start + rnge - 1)
|
||||||
|
for (start, rnge) in list(zip(seed_iter, seed_iter))
|
||||||
|
]
|
||||||
for translation in order:
|
for translation in order:
|
||||||
print(translation)
|
|
||||||
print(seeds)
|
|
||||||
new_to_convert = []
|
new_to_convert = []
|
||||||
current_map = inpt.maps[translation]
|
current_map = inpt.maps[translation]
|
||||||
# print(seeds[1])
|
|
||||||
# print(current_map)
|
|
||||||
for seed in seeds:
|
for seed in seeds:
|
||||||
cur_range_start, cur_range_range = seed
|
cur_start, cur_end = seed
|
||||||
cur_end = cur_range_start + cur_range_range
|
index = current_map.find_bucket(cur_start)
|
||||||
index = current_map.find_bucket(cur_range_start)
|
|
||||||
if index is not None:
|
if index is not None:
|
||||||
# print(current_map.maps[index])
|
section_start, section_offset, section_end = current_map.maps[index]
|
||||||
section_start, section_offset, section_range = current_map.maps[index]
|
while cur_end > section_end:
|
||||||
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:
|
if index == len(current_map.maps) - 1:
|
||||||
new_to_convert.append((section_end, cur_end - section_start))
|
new_to_convert.append((section_end + 1, cur_end))
|
||||||
else:
|
break
|
||||||
next_start, next_offset, next_range = current_map.maps[index + 1]
|
new_to_convert.append(
|
||||||
next_end = next_start + next_range
|
(cur_start + section_offset, section_end + section_offset)
|
||||||
new_to_convert.append((section_end + next_offset, cur_end - section_start))
|
)
|
||||||
if cur_end > next_end:
|
index += 1
|
||||||
print("Oh no")
|
section_start, section_offset, section_end = current_map.maps[
|
||||||
|
index
|
||||||
|
]
|
||||||
|
cur_start = section_start
|
||||||
|
|
||||||
|
new_to_convert.append(
|
||||||
|
(cur_start + section_offset, cur_end + section_offset)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
new_to_convert.append(seed)
|
new_to_convert.append(seed)
|
||||||
seeds = new_to_convert
|
seeds = new_to_convert
|
||||||
|
|
||||||
|
return min(x[0] for x in seeds)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
# return min(inpt.convert("seed", "location", x) for x in seeds)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
day5 = Day05()
|
day5 = Day05()
|
||||||
print(day5.run_example_2())
|
day5.run()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Add table
Reference in a new issue