From e4aff38d54135b3295a5ea85a1eb93403ddd1a3a Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Mon, 8 Jan 2024 08:49:04 +0100 Subject: [PATCH] Day 12 - delete brute force approach --- day12_bf.py | 212 ---------------------------------------------------- 1 file changed, 212 deletions(-) delete mode 100644 day12_bf.py diff --git a/day12_bf.py b/day12_bf.py deleted file mode 100644 index 1c6014f..0000000 --- a/day12_bf.py +++ /dev/null @@ -1,212 +0,0 @@ -import re -from tools.aoc import AOCDay -from tools.int_seq import triangular -from typing import Any, Iterable - - -def is_Valid(springs: str, groups: list[int]) -> bool: - foo = [] - h_count = 0 - for c in springs: - if c == "#": - h_count += 1 - elif h_count > 0: - foo.append(h_count) - h_count = 0 - - if h_count > 0: - foo.append(h_count) - - return foo == groups - - -def sums(length: int, total_sum: int) -> Iterable[tuple]: - if length == 1: - yield (total_sum,) - else: - for v in range(total_sum + 1): - for p in sums(length - 1, total_sum - v): - yield (v,) + p - - -def get_options(groups: list[int], fill: list[int]) -> Iterable[str]: - missing_len = sum(fill) - # print("fill_len", len(fill), "miss_len", missing_len) - for opt in sums(len(fill), missing_len): - ret = "" - for i, c in enumerate(opt): - if 0 < i < len(fill) - 1 and c == 0: - break - ret += " " * c - if i < len(groups): - ret += "#" * groups[i] - else: - yield ret - - -def get_arrangements(springs: str, groups: list[int]) -> int: - arrangements = 0 - springs = springs.replace(".", " ") - - after_fill = len(springs) - sum(groups) - len(groups) + 1 - if after_fill == 0: - return 1 - - fill = [0] + [1] * (len(groups) - 1) + [after_fill] - p = re.compile(springs.replace("?", ".")) - for s in get_options(groups, fill): - if p.match(s): - arrangements += 1 - - return arrangements - - -def _get_arrangements(springs: str, groups: list[int]): - springs, not_found = clean_springs(springs, groups) - # print("not_found", not_found) - open_groups = get_open_groups(springs) - to_determine = [] - for start, group_str in open_groups: - # print("look in", group_str, "for", [groups[x] for x in not_found]) - assigned = [] - for need in list(not_found): - # print("check", need, groups[need]) - if groups[need] > len(group_str): - continue - elif not assigned or sum(assigned) + len(assigned) + groups[need] <= len(group_str): - assigned.append(groups[need]) - not_found = not_found[1:] - else: - break - # print("append", assigned) - if assigned: - to_determine.append((group_str, assigned)) - - arrangements = 1 - for group_str, values in to_determine: - if len(values) == 1 and len(group_str) == values[0]: - continue - elif sum(values) + len(values) - 1 == len(group_str): - continue - elif len(values) == 1: - arrangements *= len(group_str) - values[0] + 1 - else: - arrangements *= triangular(len(group_str) - (sum(values) + len(values) - 1) + 1) - # print( - # group_str, - # "with", - # values, - # "has multiple options:", - # triangular(len(group_str) - (sum(values) + len(values) - 1) + 1), - # ) - - if arrangements < 0: - # print(springs, groups, to_determine) - exit(1) - - return arrangements - - -def clean_springs(springs: str, groups: list[int]) -> (str, list[int]): - hashes = [] - start = None - c_size = 0 - for i, c in enumerate(springs): - if c == "#": - if start is None: - start = i - c_size += 1 - else: - if start is not None: - hashes.append((start, c_size)) - start = None - c_size = 0 - - if start is not None: - hashes.append((start, c_size)) - - # print("cleaning", springs, "with hashes", hashes, "and groups", groups) - found = [] - for i, s in enumerate(groups): - for h in hashes: - if h[0] >= sum(groups[:i]) + i and h[0] <= len(springs) - (sum(groups[i:]) + len(groups) - i) + 1: - # print(h[0], ">", sum(groups[:i]) + i) - # print(h[0], "<", len(springs) - (sum(groups[i:]) + len(groups) - i) + 1) - if h[1] == s: - found.append(i) - if i == 0: - springs = "#" * h[1] + "." + springs[h[0] + h[1] + 1 :] - elif i == len(springs) - 1: - springs = springs[: -(h[0] + h[1] + 1)] + "." + "#" * h[1] - else: - springs = springs[: h[0] - 1] + "." + "#" * h[1] + "." + springs[h[0] + h[1] + 1 :] - # print("found index", i, "value", groups[i], "at", h[0], "new springs", springs) - break - - # print("cleaned springs", springs, "found", found) - - return springs, [x for x in range(len(groups)) if x not in found] - - -def get_open_groups(springs: str) -> list[tuple[int, str]]: - open_groups = [] - start = None - group_str = "" - for i, c in enumerate(springs): - if c == ".": - if "?" in group_str: - open_groups.append((start, group_str)) - start = None - group_str = "" - else: - if start is None: - start = i - group_str += c - - if "?" in group_str: - open_groups.append((start, group_str)) - - return open_groups - - -class Day(AOCDay): - inputs = [ - [ - (21, "input12_test"), - (6981, "input12"), - ], - [ - (525152, "input12_test"), - (None, "input12"), - ], - ] - - def part1(self) -> Any: - ans = 0 - for line in self.getInput(): - springs, groups = line.split() - groups = list(map(int, groups.split(","))) - f = get_arrangements(springs, groups) - print("RESULT", springs, "=>", f) - ans += f - - return ans - - def part2(self) -> Any: - return "" - ans = 0 - for i, line in enumerate(self.getInput()): - springs, groups = line.split() - groups = list(map(int, groups.split(","))) - springs = "?".join([springs] * 5) - groups = groups * 5 - f = get_arrangements(springs, groups) - print(i + 1, "/", len(self.input), "=>", f) - ans += f - - return ans - - -if __name__ == "__main__": - day = Day(2023, 12) - day.run(verbose=True)