diff --git a/2020/day21.py b/2020/day21.py new file mode 100644 index 0000000..0960933 --- /dev/null +++ b/2020/day21.py @@ -0,0 +1,43 @@ +import re +import sys +from functools import reduce + +LINE_RE = re.compile(r"(.+) \(contains (.+)\)") + +def main(): + lines = [line.rstrip() for line in sys.stdin] + foods = [] + for line in lines: + i, a = LINE_RE.match(line).groups() + foods.append((set(i.split()), set(a.split(", ")))) + ingredients = set(i for il, _ in foods for i in il) + allergens = set(a for _, al in foods for a in al) + + # Part 1 + matches = {} + while len(matches) < len(allergens): + for allergen in allergens: + p_ings = [ + set(filter(lambda i: i not in matches, f[0])) + for f in foods if allergen in f[1] + ] + c_ings = reduce(lambda a, b: a & b, p_ings, ingredients) + if len(c_ings) == 1: + i = c_ings.pop() + matches[i] = allergen + clean_ings = ingredients.difference(set(matches.keys())) + num_appearances = sum( + ci in fis + for fis, _ in foods + for ci in clean_ings + ) + print(f"Clean ingredients appear {num_appearances} times.") + + # Part 2 + canonical = ",".join( + f for f, a in sorted(matches.items(), key=lambda m: m[1]) + ) + print("Canonical list:", canonical) + +if __name__ == "__main__": + main()