Advent of Code, día 21
Un respiro en este día 21
Parte 1
Muy parecida a la parte 2 del día 16.
En la primera mitad del código, parseamos la entrada y vamos calculando los posibles ingredientes para cada alérgeno: para cada alérgeno en cada comida, calculamos la intersección de los ingredientes posibles (que teníamos de las comidas anteriores) con los ingredientes que vemos en esta línea.
def solve(input):
possible_ingredients = {}
ingredients_count = Counter()
for food in input.strip().split('\n'):
ingredients, allergens = re.fullmatch(
'(.*) \(contains (.*)\)', food).groups()
ingredients = ingredients.split()
allergens = allergens.split(', ')
for ingredient in ingredients:
ingredients_count[ingredient] += 1
for allergen in allergens:
if allergen not in possible_ingredients:
possible_ingredients[allergen] = set(ingredients)
else:
possible_ingredients[allergen] &= set(ingredients)
# resolve multiple possibilities by elimination
solved_ingredients = {}
while possible_ingredients:
allergen, ingredients = min(
possible_ingredients.items(),
key=lambda pair: len(pair[1])
)
assert len(ingredients) == 1
ingredient = ingredients.pop()
solved_ingredients[ingredient] = allergen
possible_ingredients.pop(allergen)
for other_ingredients in possible_ingredients.values():
other_ingredients -= {ingredient}
return sum(
count
for ingredient, count in ingredients_count.items()
if ingredient not in solved_ingredients
)
La segunda mitad del código se encarga de resolver por eliminación las posibilidades (mismo código que el día 16 parte 2) y finalmente calcular el resultado.
Parte 2
El código es muy parecido… prácticamente solo cambia el return.
def solve(input):
possible_ingredients = {}
foods = []
for food in input.strip().split('\n'):
ingredients, allergens = re.fullmatch(
'(.*) \(contains (.*)\)', food).groups()
ingredients = ingredients.split()
allergens = allergens.split(', ')
foods.append(set(ingredients))
for allergen in allergens:
if allergen not in possible_ingredients:
possible_ingredients[allergen] = set(ingredients)
else:
possible_ingredients[allergen] &= set(ingredients)
# resolve multiple possibilities by elimination
solved_ingredients = {}
while possible_ingredients:
allergen, ingredients = min(
possible_ingredients.items(),
key=lambda pair: len(pair[1])
)
assert len(ingredients) == 1
ingredient = ingredients.pop()
solved_ingredients[ingredient] = allergen
possible_ingredients.pop(allergen)
for other_ingredients in possible_ingredients.values():
other_ingredients -= {ingredient}
return ','.join(
ingredient
for allergen, ingredient in (
sorted(
(allergen, ingredient)
for ingredient, allergen in solved_ingredients.items()
)
)
)
Un descansito para retomar energías y ¡aguantar hasta el final!
El código completo aquí: https://github.com/jabadia/adventOfCode2020/tree/main/d22