diff --git a/aoc/day12.py b/aoc/day12.py index 5c24375..d7565c2 100644 --- a/aoc/day12.py +++ b/aoc/day12.py @@ -1,28 +1,11 @@ from __future__ import annotations from typing import TypeAlias from dataclasses import dataclass -from itertools import groupby, takewhile, compress +from itertools import groupby from collections import deque 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 class Line: @@ -39,6 +22,17 @@ class Line: 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] P2: TypeAlias = list[Line] @@ -49,7 +43,7 @@ class Day12(AocParseLines[Line, Line], Aoc2[P1, P2]): return Line.from_str(inpt) def parseline2(self, inpt: str) -> Line: - return Line.from_str(inpt) + return Line.from_str2(inpt) @staticmethod 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] segment = line[startpos : startpos + length] stopper = line[startpos + length] - return ( - starter != "#" - and stopper != "#" - and (len(segment) >= length) - and ("." not in segment) - ) + return starter != "#" and stopper != "#" and ("." not in segment) def part1(self, inpt: P1) -> int: accum = 0 + # inpt = inpt[:1] + # print(inpt) for line in inpt: belegungen = [[0]] - for group in line.groups: + for i, group in enumerate(line.groups): # print(f"{belegungen=}") next_belegungen = [] for belegung in belegungen: last_end = belegung[-1] # 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)): + # print(startvalue) + if "#" in line.springs[last_end:startvalue]: + continue fits = self.fits(line.springs, startvalue, group) + + if i == len(line.groups) - 1: + if "#" in line.springs[startvalue + group :]: + continue + if fits: # print(f"Y {i=}, {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=}") belegungen = next_belegungen + # print(belegungen) # print(line.springs[1:-1], line.groups, len(belegungen)) # if len(belegungen) == 1: # print( # 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): print("X") + # print(line.springs, line.groups) for belegung in belegungen: self.check_belegung(line, belegung) accum += len(belegungen) + # print(len(belegungen)) # print(belegungen) # print(belegungen) + print(accum) + return accum def check_belegung(self, line, 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): print(f"Groups Wrong in {line=}") @@ -110,13 +123,29 @@ class Day12(AocParseLines[Line, Line], Aoc2[P1, P2]): if "." in b: 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: - return 0 + for line in inpt: + print(line) + return self.part1(inpt) def main() -> None: aoc = Day12(2023, 12, example_code_nr1=1, example_code_nr2=1) - aoc.run() + aoc.run_example_2() if __name__ == "__main__":