advent-of-code/2024-python/output/day_19.py
Anders Englöf Ytterström ded5c4f28c Solve 2024:19 p1-2 "Linen Layout"
Initial tries to use a while loop instead of
recursion gave a classic AoC situation: test cases
worked, but not actual AoC puzzle input.

Turns out I only considererd removing the longest
pattern form the design, rather than consider all
possible removals.

Some Python goodies in here:

- `"abcdefgh".startswith("abc")` instead of regexp.
- removeprefix() is nice, and in some cases more
readable. `"abcdefgh".removeprefix("abc")` vs
`"abcdefgh[3:]"
- To speed things up for pt 2, functools is used
which requires a dict to be hashed as a tuple.

If one wish to solve this without recursion, a
BFS solution is most likely the way to go.

def ispossible(design, patterns):
    Q = [design]
    possible = 0
    while Q:
        remaining = Q.pop(0)
        if not remaining:
            possible += 1
            continue
        for pattern in patterns[remaining[0]]:
            if remaining.startswith(pattern):
                Q.append(remaining.removeprefix(pattern))
    return possible
2025-01-05 00:06:18 +01:00

39 lines
994 B
Python

from functools import cache
from collections import defaultdict
def solve(data):
patterns, designs = data.split("\n\n")
patterns = sorted(patterns.split(", "), key=lambda s: -len(s))
designs = designs.split()
hashed = defaultdict(list)
for p in patterns:
hashed[p[0]].append(p)
hashed = tuple([(k, tuple(v)) for k, v in hashed.items()])
possible = sum(ispossible(d, hashed) > 0 for d in designs)
every_possibility = sum(ispossible(d, hashed) for d in designs)
return possible, every_possibility
@cache
def ispossible(remaining, patterns):
if not remaining:
return 1
selected = dict(patterns).get(remaining[0], [])
return sum(
ispossible(remaining.removeprefix(pattern), patterns)
for pattern in selected
if remaining.startswith(pattern)
)
if __name__ == "__main__":
with open("./input/19.txt", "r") as f:
inp = f.read().strip()
p1, p2 = solve(inp)
print(p1)
print(p2)