Skip to content

Commit

Permalink
AoC 2024 day 19 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
loociano committed Dec 21, 2024
1 parent e1784b7 commit b1c8720
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 10 deletions.
40 changes: 31 additions & 9 deletions aoc2024/src/day19/python/solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,41 @@

@cache
def _is_possible(design: str, patterns: frozenset[str], candidate: str = '') -> bool:
"""Returns true if the design can be made with the available patterns."""
for pattern in patterns:
testee = candidate + pattern
if testee == design:
if testee == design or (design.startswith(testee) and _is_possible(design, patterns, testee)):
return True
if design.startswith(testee):
if _is_possible(design, patterns, testee):
return True
return False


@cache
def _count_distinct_arrangements(design: str, patterns: frozenset[str], prefix: str, k: int) -> int:
"""Returns the number of distinct arrangements that can be made to create a 'design'
from available 'patterns'.
Example: given design 'brwrr' and patterns 'b','r','br','wr',
it can be made in 2 different ways: b+r+wr+r or br+wr+r."""
if k == 0: # Base case
return 1
return sum(
_count_distinct_arrangements(design=design,
patterns=patterns,
prefix=prefix + pattern,
k=k - len(pattern))
if design.startswith(prefix + pattern)
else 0
for pattern in patterns)


def num_possible_designs(input: Sequence[str]) -> int:
patterns: frozenset[str] = frozenset(input[0].split(', '))
result = 0
for design in input[2:]:
result += 1 if _is_possible(design, patterns) else 0
return result
"""Returns the total number of designs that can be made with the available patterns."""
patterns: frozenset[str] = frozenset(input[0].split(', ')) # First line has comma-separated patterns.
return sum(1 if _is_possible(design, patterns) else 0
for design in input[2:]) # Designs start on the third line.


def num_possible_options(input: Sequence[str]) -> int:
"""Returns the total number of different ways the designs can be made with the available patterns."""
patterns: frozenset[str] = frozenset(input[0].split(', ')) # First line has comma-separated patterns.
return sum(_count_distinct_arrangements(design=design, patterns=patterns, prefix='', k=len(design))
for design in input[2:]) # Designs start on the third line.
8 changes: 7 additions & 1 deletion aoc2024/test/day19/python/test_solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import unittest

from common.python3.AdventOfCodeTestCase import AdventOfCodeTestCase
from aoc2024.src.day19.python.solution import num_possible_designs
from aoc2024.src.day19.python.solution import num_possible_designs, num_possible_options


class TestSolution(AdventOfCodeTestCase):
Expand All @@ -28,6 +28,12 @@ def test_part1_withExample_success(self):
def test_part1_withPuzzleInput_success(self):
self.assertEqual(365, num_possible_designs(self.input))

def test_part2_withExample_success(self):
self.assertEqual(16, num_possible_options(self.examples[0]))

def test_part2_withPuzzleInput_success(self):
self.assertEqual(730121486795169, num_possible_options(self.input))


if __name__ == '__main__':
unittest.main()

0 comments on commit b1c8720

Please sign in to comment.