Advent of Code, día 21

Javier Abadia
2 min readDec 22, 2020

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

--

--

Javier Abadia

VP of Engineering en StyleSage. Me encanta desarrollar software en equipo, buscar los obstáculos que nos hacen ir más despacio y eliminarlos