aoc2023/day12.py
2024-01-08 08:48:25 +01:00

75 lines
2.2 KiB
Python

from tools.aoc import AOCDay
from typing import Any
def get_min_len(groups: tuple[int, ...]) -> int:
return sum(groups) + len(groups) - 1
class Day(AOCDay):
inputs = [
[
(21, "input12_test"),
(101, "input12_debug"),
(6981, "input12"),
],
[
(525152, "input12_test"),
(4546215031609, "input12"),
],
]
def parse_input(self, part2: bool = False) -> list[tuple[str, tuple[int, ...]]]:
records = []
for line in self.getInput():
springs, groups = line.split()
groups = tuple(map(int, groups.split(",")))
if part2:
springs = "?".join([springs] * 5)
groups *= 5
records.append((springs, groups))
return records
def get_arrangements(self, springs: str, groups: tuple[int, ...]) -> int:
if (springs, groups) in self.DP:
return self.DP[(springs, groups)]
if len(groups) == 0:
return 0
count = 0
for i in range(len(springs) - get_min_len(groups) + 1):
sub_springs = springs[i:]
hash_len = groups[0]
if (
(i > 0 and springs[i - 1] == "#")
or "." in sub_springs[:hash_len]
or (len(sub_springs) > hash_len and sub_springs[hash_len] == "#")
):
if "#" in springs[:i]:
break
else:
continue
if len(groups) > 1:
count += self.get_arrangements(springs[i + groups[0] + 1 :], groups[1:])
else:
if "#" in springs[i + groups[0] :]:
continue
count += 1
self.DP[(springs, groups)] = count
return self.DP[(springs, groups)]
def part1(self) -> Any:
return sum(self.get_arrangements(springs, groups) for springs, groups in self.parse_input())
def part2(self) -> Any:
return sum(self.get_arrangements(springs, groups) for springs, groups in self.parse_input(part2=True))
if __name__ == "__main__":
day = Day(2023, 12)
day.run(verbose=True)