-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday19.py
More file actions
115 lines (89 loc) · 3.39 KB
/
Copy pathday19.py
File metadata and controls
115 lines (89 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from functools import lru_cache
filepath = "day19.txt"
def read_file():
lines = [line.strip() for line in open(filepath)]
towels = lines[0].split(", ")
designs = lines[2:]
return towels, designs
def is_composite(string, parts):
if not string:
return True
for part in parts:
if string.startswith(part):
if is_composite(string[len(part):], parts):
return True
return False
def clean_towels(towels):
towels = list(set(towels))
towels = set(sorted(towels, key = len))
cleaned_towels = [
towel for towel in towels if not is_composite(towel, towels - {towel})
]
return cleaned_towels
def find_combination(design, towels):
all_fitting_start_towels = [towel for towel in towels if design.startswith(towel)]
#print("Design: ", design)
#print("All fitting towels", all_fitting_start_towels)
result = False
for towel in all_fitting_start_towels:
#print("Checking towel ", towel)
if len(design[len(towel):]) != 0:
result = find_combination(design[len(towel):], towels)
if result:
return True
else:
continue
else:
#print("Design Found")
return True
return result
def find_all_combinations(design, towels):
@lru_cache(None)
def helper(design):
# Base case: if the design is empty, we found a valid combination
if not design:
return [[]] # Return a list with an empty combination
# Get all towels that fit the start of the current design
all_fitting_start_towels = [towel for towel in towels if design.startswith(towel)]
# If no towels fit, return empty list
if not all_fitting_start_towels:
return []
# Store all valid combinations for the current design
all_combinations = []
# Try each towel and recursively find combinations
for towel in all_fitting_start_towels:
remaining_design = design[len(towel):]
sub_combinations = helper(remaining_design)
# Limit memory usage by avoiding nested combination generation if sub_combinations is too large
#if len(sub_combinations) > 50000: # Arbitrary threshold to prevent memory explosion
# continue
all_combinations.extend([[towel] + combination for combination in sub_combinations])
return all_combinations
return helper(design)
def solve_part_i():
towels, designs = read_file()
towels = clean_towels(towels)
result = 0
for design in designs:
print(f"Design: {design}")
if find_combination(design, towels):
result += 1
print("-------------------------------------------------------------------------------")
print(f"Part I: {result}")
def solve_part_ii():
towels, designs = read_file()
cleaned_towels = clean_towels(towels)
result = 0
working_designs = []
for design in designs:
if find_combination(design, cleaned_towels):
working_designs.append(design)
print(f"Found all {len(working_designs)} working combinations")
for design in working_designs:
print("Design", design)
combinations = find_all_combinations(design, towels)
#print(combinations)
result += len(combinations)
print(f"Part I: {result}")
# solve_part_i()
solve_part_ii()