diff --git a/aoc/day12.py b/aoc/day12.py index f919fd0..5c24375 100644 --- a/aoc/day12.py +++ b/aoc/day12.py @@ -1,13 +1,26 @@ from __future__ import annotations from typing import TypeAlias from dataclasses import dataclass -from itertools import groupby, takewhile +from itertools import groupby, takewhile, compress from collections import deque from .aoc import Aoc2, AocParseLines """ -?###???????? 3,2,1 +?###.??????? 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 """ @@ -24,7 +37,7 @@ class Line: springs_group = deque((len(list(d)), i) for i, d in groupby(springs)) - return Line(springs, springs_group, groups) + return Line("." + springs + ".", springs_group, groups) P1: TypeAlias = list[Line] @@ -38,22 +51,72 @@ class Day12(AocParseLines[Line, Line], Aoc2[P1, P2]): def parseline2(self, inpt: str) -> Line: return Line.from_str(inpt) - def part1(self, inpt: P1) -> int: - for line in inpt: - sgroups = line.spring_groups - for group in line.groups: - batch = takewhile(lambda g: g[1] != ".", sgroups) - first_group = sgroups.popleft() + @staticmethod + def fits(line: str, startpos: int, length: int) -> bool: + if startpos + length >= len(line): + return False + 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 0 + def part1(self, inpt: P1) -> int: + accum = 0 + for line in inpt: + belegungen = [[0]] + for group in 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)=}") + for startvalue in range(last_end + 1, len(line.springs)): + fits = self.fits(line.springs, startvalue, group) + if fits: + # print(f"Y {i=}, {startvalue=}, {group=}") + next_belegungen.append(belegung + [startvalue + group]) + # else: + # print(f"N {i=}, {startvalue=}, {group=}") + + belegungen = next_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]]}" + # ) + if len(set((tuple(x) for x in belegungen))) != len(belegungen): + print("X") + for belegung in belegungen: + self.check_belegung(line, belegung) + accum += len(belegungen) + # print(belegungen) + # print(belegungen) + + return accum + + def check_belegung(self, line, belegung): + if "#" in [line.springs[x] for x in belegung]: + print(f"Wron # in {line=}") + if len(belegung) != 1 + len(line.groups): + print(f"Groups Wrong in {line=}") + + for ends, lengths in zip(belegung[1:], line.groups): + b = line.springs[ends - lengths : ends] + if "." in b: + print("{line=}") def part2(self, inpt: P2) -> int: return 0 def main() -> None: - aoc = Day12(2023, 12, example_code_nr1=1) - aoc.run_example_1() + aoc = Day12(2023, 12, example_code_nr1=1, example_code_nr2=1) + aoc.run() if __name__ == "__main__":