Skip to content

Commit bff2058

Browse files
committed
Added second method for 2020-21
1 parent b531317 commit bff2058

File tree

2 files changed

+196
-66
lines changed

2 files changed

+196
-66
lines changed

2020/21-Allergen Assessment.py

Lines changed: 36 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ def words(s: str):
4141
"expected": ["5", "mxmxvkd,sqjhc,fvjkl"],
4242
}
4343

44+
test += 1
45+
test_data[test] = {
46+
"input": """mxmxvkd kfcds sqjhc nhms (contains dairy, fish)
47+
trh fvjkl sbzzf mxmxvkd (contains dairy)
48+
sqjhc fvjkl (contains soy)
49+
sqjhc mxmxvkd sbzzf (contains fish)""",
50+
"expected": ["5", "mxmxvkd,sqjhc,fvjkl"],
51+
}
52+
4453
test = "real"
4554
input_file = os.path.join(
4655
os.path.dirname(__file__),
@@ -67,88 +76,49 @@ def words(s: str):
6776

6877
# -------------------------------- Actual code execution ----------------------------- #
6978

70-
all_ingredients = defaultdict(int)
71-
all_allergens = {}
72-
nb_allergens = defaultdict(int)
73-
allergens_ingredients = {}
79+
all_allergens = set()
80+
all_ingredients = {}
81+
allergen_graph = graph.WeightedGraph()
82+
allergen_graph.vertices = set()
7483

7584
for string in puzzle_input.split("\n"):
7685
if "contains" in string:
7786
ingredients = string.split(" (")[0].split(" ")
7887
allergens = string.split("(contains ")[1][:-1].split(", ")
79-
if isinstance(allergens, str):
80-
allergens = [allergens]
8188

82-
for allergen in allergens:
83-
nb_allergens[allergen] += 1
84-
if allergen not in all_allergens:
85-
all_allergens[allergen] = ingredients.copy()
86-
allergens_ingredients[allergen] = defaultdict(int)
87-
allergens_ingredients[allergen].update(
88-
{ingredient: 1 for ingredient in ingredients}
89-
)
89+
all_allergens = all_allergens.union(allergens)
90+
all_ingredients.update(
91+
{ing: all_ingredients.get(ing, 0) + 1 for ing in ingredients}
92+
)
9093

94+
for allergen in allergens:
95+
if allergen not in allergen_graph.edges:
96+
allergen_graph.edges[allergen] = {x: 1 for x in ingredients}
9197
else:
92-
for ingredient in ingredients:
93-
allergens_ingredients[allergen][ingredient] += 1
94-
for ingredient in all_allergens[allergen].copy():
95-
if ingredient not in ingredients:
96-
all_allergens[allergen].remove(ingredient)
97-
98-
for ingredient in ingredients:
99-
all_ingredients[ingredient] += 1
98+
for ing in allergen_graph.edges[allergen].copy():
99+
if ing not in ingredients:
100+
del allergen_graph.edges[allergen][ing]
100101

101102
else:
102103
print("does not contain any allergen")
103104

104-
105-
for allergen in test:
106-
if allergen != "shellfish":
107-
continue
108-
print(
109-
allergen,
110-
test2[allergen],
111-
[ing for ing, val in test[allergen].items() if val == test2[allergen]],
112-
)
113-
114-
sum_ingredients = 0
115-
for ingredient in all_ingredients:
116-
if not (any(ingredient in val for val in all_allergens.values())):
117-
sum_ingredients += all_ingredients[ingredient]
105+
allergen_graph.vertices = list(all_allergens.union(set(all_ingredients.keys())))
106+
allergen_graph.bipartite_matching(all_allergens, all_ingredients)
118107

119108
if part_to_test == 1:
120-
puzzle_actual_result = sum_ingredients
121-
109+
safe_ingredients = [
110+
x for x in allergen_graph.vertices if allergen_graph.flow_graph[x] == {}
111+
]
112+
safe_number = sum(all_ingredients[x] for x in safe_ingredients)
113+
puzzle_actual_result = safe_number
122114

123115
else:
124-
allergens_ingredients = {
125-
aller: [
126-
ing
127-
for ing, val in allergens_ingredients[aller].items()
128-
if val == nb_allergens[aller]
129-
]
130-
for aller in nb_allergens
131-
}
132-
final_allergen = {}
133-
while len(final_allergen) != len(nb_allergens):
134-
for allergen, val in allergens_ingredients.items():
135-
if len(val) == 1:
136-
final_allergen[allergen] = val[0]
137-
138-
allergens_ingredients = {
139-
aller: [
140-
ing
141-
for ing in allergens_ingredients[aller]
142-
if ing not in final_allergen.values()
143-
]
144-
for aller in nb_allergens
145-
}
146-
147-
print(final_allergen)
148-
ing_list = ""
149-
for aller in sorted(final_allergen.keys()):
150-
ing_list += final_allergen[aller] + ","
151-
puzzle_actual_result = ing_list[:-1]
116+
dangerous_ingredients = [
117+
list(allergen_graph.flow_graph[aller].keys())[0]
118+
for aller in sorted(all_allergens)
119+
]
120+
puzzle_actual_result = ",".join(dangerous_ingredients)
121+
152122

153123
# -------------------------------- Outputs / results --------------------------------- #
154124

2020/21-Allergen Assessment.v1.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# -------------------------------- Input data ---------------------------------------- #
2+
import os, grid, graph, dot, assembly, re, itertools
3+
from collections import Counter, deque, defaultdict
4+
5+
from compass import *
6+
7+
8+
# This functions come from https://github.com/mcpower/adventofcode - Thanks!
9+
def lmap(func, *iterables):
10+
return list(map(func, *iterables))
11+
12+
13+
def ints(s: str):
14+
return lmap(int, re.findall(r"-?\d+", s)) # thanks mserrano!
15+
16+
17+
def positive_ints(s: str):
18+
return lmap(int, re.findall(r"\d+", s)) # thanks mserrano!
19+
20+
21+
def floats(s: str):
22+
return lmap(float, re.findall(r"-?\d+(?:\.\d+)?", s))
23+
24+
25+
def positive_floats(s: str):
26+
return lmap(float, re.findall(r"\d+(?:\.\d+)?", s))
27+
28+
29+
def words(s: str):
30+
return re.findall(r"[a-zA-Z]+", s)
31+
32+
33+
test_data = {}
34+
35+
test = 1
36+
test_data[test] = {
37+
"input": """mxmxvkd kfcds sqjhc nhms (contains dairy, fish)
38+
trh fvjkl sbzzf mxmxvkd (contains dairy)
39+
sqjhc fvjkl (contains soy)
40+
sqjhc mxmxvkd sbzzf (contains fish)""",
41+
"expected": ["5", "mxmxvkd,sqjhc,fvjkl"],
42+
}
43+
44+
test = "real"
45+
input_file = os.path.join(
46+
os.path.dirname(__file__),
47+
"Inputs",
48+
os.path.basename(__file__).replace(".py", ".txt"),
49+
)
50+
test_data[test] = {
51+
"input": open(input_file, "r+").read(),
52+
"expected": ["2410", "tmp,pdpgm,cdslv,zrvtg,ttkn,mkpmkx,vxzpfp,flnhl"],
53+
}
54+
55+
56+
# -------------------------------- Control program execution ------------------------- #
57+
58+
case_to_test = "real"
59+
part_to_test = 2
60+
61+
# -------------------------------- Initialize some variables ------------------------- #
62+
63+
puzzle_input = test_data[case_to_test]["input"]
64+
puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1]
65+
puzzle_actual_result = "Unknown"
66+
67+
68+
# -------------------------------- Actual code execution ----------------------------- #
69+
70+
all_ingredients = defaultdict(int)
71+
all_allergens = {}
72+
nb_allergens = defaultdict(int)
73+
allergens_ingredients = {}
74+
75+
for string in puzzle_input.split("\n"):
76+
if "contains" in string:
77+
ingredients = string.split(" (")[0].split(" ")
78+
allergens = string.split("(contains ")[1][:-1].split(", ")
79+
if isinstance(allergens, str):
80+
allergens = [allergens]
81+
82+
for allergen in allergens:
83+
nb_allergens[allergen] += 1
84+
if allergen not in all_allergens:
85+
all_allergens[allergen] = ingredients.copy()
86+
allergens_ingredients[allergen] = defaultdict(int)
87+
allergens_ingredients[allergen].update(
88+
{ingredient: 1 for ingredient in ingredients}
89+
)
90+
91+
else:
92+
for ingredient in ingredients:
93+
allergens_ingredients[allergen][ingredient] += 1
94+
for ingredient in all_allergens[allergen].copy():
95+
if ingredient not in ingredients:
96+
all_allergens[allergen].remove(ingredient)
97+
98+
for ingredient in ingredients:
99+
all_ingredients[ingredient] += 1
100+
101+
else:
102+
print("does not contain any allergen")
103+
104+
105+
for allergen in test:
106+
if allergen != "shellfish":
107+
continue
108+
print(
109+
allergen,
110+
test2[allergen],
111+
[ing for ing, val in test[allergen].items() if val == test2[allergen]],
112+
)
113+
114+
sum_ingredients = 0
115+
for ingredient in all_ingredients:
116+
if not (any(ingredient in val for val in all_allergens.values())):
117+
sum_ingredients += all_ingredients[ingredient]
118+
119+
if part_to_test == 1:
120+
puzzle_actual_result = sum_ingredients
121+
122+
123+
else:
124+
allergens_ingredients = {
125+
aller: [
126+
ing
127+
for ing, val in allergens_ingredients[aller].items()
128+
if val == nb_allergens[aller]
129+
]
130+
for aller in nb_allergens
131+
}
132+
final_allergen = {}
133+
while len(final_allergen) != len(nb_allergens):
134+
for allergen, val in allergens_ingredients.items():
135+
if len(val) == 1:
136+
final_allergen[allergen] = val[0]
137+
138+
allergens_ingredients = {
139+
aller: [
140+
ing
141+
for ing in allergens_ingredients[aller]
142+
if ing not in final_allergen.values()
143+
]
144+
for aller in nb_allergens
145+
}
146+
147+
print(final_allergen)
148+
ing_list = ""
149+
for aller in sorted(final_allergen.keys()):
150+
ing_list += final_allergen[aller] + ","
151+
puzzle_actual_result = ing_list[:-1]
152+
153+
# -------------------------------- Outputs / results --------------------------------- #
154+
155+
print("Case :", case_to_test, "- Part", part_to_test)
156+
print("Expected result : " + str(puzzle_expected_result))
157+
print("Actual result : " + str(puzzle_actual_result))
158+
# Date created: 2020-12-21 06:07:34.505688
159+
# Part 1: 2020-12-21 07:22:36
160+
# Part 2: 2020-12-21 07:30:15

0 commit comments

Comments
 (0)