Day12 part 1

This commit is contained in:
Christoph Stahl 2023-12-13 21:33:06 +01:00
parent 9854bf2c99
commit ef470926c0

View file

@ -1,28 +1,11 @@
from __future__ import annotations from __future__ import annotations
from typing import TypeAlias from typing import TypeAlias
from dataclasses import dataclass from dataclasses import dataclass
from itertools import groupby, takewhile, compress from itertools import groupby
from collections import deque from collections import deque
from .aoc import Aoc2, AocParseLines from .aoc import Aoc2, AocParseLines
"""
?###.??????? 3,2,1
1 2 3
? 0 0 0
# 0 0 0
# 1 0 0
# 2 0 0
. 2 0 0
? 2 0 0
? 2 3 0
? 2 4 0
? 2 5 2
? 2 6 3
"""
@dataclass @dataclass
class Line: class Line:
@ -39,6 +22,17 @@ class Line:
return Line("." + springs + ".", springs_group, groups) return Line("." + springs + ".", springs_group, groups)
@classmethod
def from_str2(cls, inpt: str) -> Line:
springs, groups_str = inpt.split(" ")
springs = "?".join([springs] * 5)
groups = [int(d) for d in groups_str.split(",")]
groups = groups + groups + groups + groups + groups
springs_group = deque((len(list(d)), i) for i, d in groupby(springs))
return Line("." + springs + ".", springs_group, groups)
P1: TypeAlias = list[Line] P1: TypeAlias = list[Line]
P2: TypeAlias = list[Line] P2: TypeAlias = list[Line]
@ -49,7 +43,7 @@ class Day12(AocParseLines[Line, Line], Aoc2[P1, P2]):
return Line.from_str(inpt) return Line.from_str(inpt)
def parseline2(self, inpt: str) -> Line: def parseline2(self, inpt: str) -> Line:
return Line.from_str(inpt) return Line.from_str2(inpt)
@staticmethod @staticmethod
def fits(line: str, startpos: int, length: int) -> bool: def fits(line: str, startpos: int, length: int) -> bool:
@ -58,25 +52,35 @@ class Day12(AocParseLines[Line, Line], Aoc2[P1, P2]):
starter = line[startpos - 1] starter = line[startpos - 1]
segment = line[startpos : startpos + length] segment = line[startpos : startpos + length]
stopper = line[startpos + length] stopper = line[startpos + length]
return ( return starter != "#" and stopper != "#" and ("." not in segment)
starter != "#"
and stopper != "#"
and (len(segment) >= length)
and ("." not in segment)
)
def part1(self, inpt: P1) -> int: def part1(self, inpt: P1) -> int:
accum = 0 accum = 0
# inpt = inpt[:1]
# print(inpt)
for line in inpt: for line in inpt:
belegungen = [[0]] belegungen = [[0]]
for group in line.groups: for i, group in enumerate(line.groups):
# print(f"{belegungen=}") # print(f"{belegungen=}")
next_belegungen = [] next_belegungen = []
for belegung in belegungen: for belegung in belegungen:
last_end = belegung[-1] last_end = belegung[-1]
# print(f"{last_start=}, {last_end=}, {group=}, {len(line.springs)=}") # print(f"{last_start=}, {last_end=}, {group=}, {len(line.springs)=}")
# try:
# first_hash = line.springs[last_end:].index("#") + 1
# # print("First hash", first_hash)
# except ValueError:
# first_hash = len(line.springs) - 1
for startvalue in range(last_end + 1, len(line.springs)): for startvalue in range(last_end + 1, len(line.springs)):
# print(startvalue)
if "#" in line.springs[last_end:startvalue]:
continue
fits = self.fits(line.springs, startvalue, group) fits = self.fits(line.springs, startvalue, group)
if i == len(line.groups) - 1:
if "#" in line.springs[startvalue + group :]:
continue
if fits: if fits:
# print(f"Y {i=}, {startvalue=}, {group=}") # print(f"Y {i=}, {startvalue=}, {group=}")
next_belegungen.append(belegung + [startvalue + group]) next_belegungen.append(belegung + [startvalue + group])
@ -84,24 +88,33 @@ class Day12(AocParseLines[Line, Line], Aoc2[P1, P2]):
# print(f"N {i=}, {startvalue=}, {group=}") # print(f"N {i=}, {startvalue=}, {group=}")
belegungen = next_belegungen belegungen = next_belegungen
# print(belegungen)
# print(line.springs[1:-1], line.groups, len(belegungen)) # print(line.springs[1:-1], line.groups, len(belegungen))
# if len(belegungen) == 1: # if len(belegungen) == 1:
# print( # print(
# f"{line.springs=}, {line.groups=}, {[line.springs[x] for x in belegungen[0]]}" # f"{line.springs=}, {line.groups=}, {[line.springs[x] for x in belegungen[0]]}"
# ) # )
for belegung in belegungen:
last_belegung = belegung[-1]
if "#" in line.springs[last_belegung:]:
print(line.springs, line.groups)
if len(set((tuple(x) for x in belegungen))) != len(belegungen): if len(set((tuple(x) for x in belegungen))) != len(belegungen):
print("X") print("X")
# print(line.springs, line.groups)
for belegung in belegungen: for belegung in belegungen:
self.check_belegung(line, belegung) self.check_belegung(line, belegung)
accum += len(belegungen) accum += len(belegungen)
# print(len(belegungen))
# print(belegungen) # print(belegungen)
# print(belegungen) # print(belegungen)
print(accum)
return accum return accum
def check_belegung(self, line, belegung): def check_belegung(self, line, belegung):
if "#" in [line.springs[x] for x in belegung]: if "#" in [line.springs[x] for x in belegung]:
print(f"Wron # in {line=}") print(f"Wrong # in {line=}")
if len(belegung) != 1 + len(line.groups): if len(belegung) != 1 + len(line.groups):
print(f"Groups Wrong in {line=}") print(f"Groups Wrong in {line=}")
@ -110,13 +123,29 @@ class Day12(AocParseLines[Line, Line], Aoc2[P1, P2]):
if "." in b: if "." in b:
print("{line=}") print("{line=}")
last_end = 0
bstr = "."
for ends, lengths in zip(belegung[1:], line.groups):
beginning = ends - lengths
bstr += "." * (beginning - len(bstr))
bstr += "#" * lengths
if (line.springs[beginning - 1] == "#") or line.springs[ends] == "#":
print("X")
if beginning - last_end < 1:
print("XXX")
last_end = ends
# print(bstr)
def part2(self, inpt: P2) -> int: def part2(self, inpt: P2) -> int:
return 0 for line in inpt:
print(line)
return self.part1(inpt)
def main() -> None: def main() -> None:
aoc = Day12(2023, 12, example_code_nr1=1, example_code_nr2=1) aoc = Day12(2023, 12, example_code_nr1=1, example_code_nr2=1)
aoc.run() aoc.run_example_2()
if __name__ == "__main__": if __name__ == "__main__":