You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

45 lines
1.4KB

  1. import re
  2. import sys
  3. def words(string):
  4. return frozenset(re.findall(r'\w+', string))
  5. text = sys.stdin.read()
  6. recipes = dict(map(words, ln.split('contains')) for ln in text.splitlines())
  7. all_ingredients = {item for group in recipes.keys() for item in group}
  8. all_allergens = {item for group in recipes.values() for item in group}
  9. # any ingredient can be any allergen,
  10. # but if the allergen *is* there, and the ingredient *isn't*
  11. # then the ingredient *cannot* be the allergen
  12. options = {ingredient: set(all_allergens) for ingredient in all_ingredients}
  13. for ingredients, allergens in recipes.items():
  14. for f2 in all_ingredients - ingredients:
  15. options[f2] -= allergens
  16. clean = {ing for ing, als in options.items() if not als}
  17. ans = sum(len(recipe & clean) for recipe in recipes)
  18. print(ans)
  19. def recurse(leftover, known=[]):
  20. if not leftover:
  21. yield dict(known)
  22. else:
  23. ing, = key = min(leftover, key=len)
  24. for alg in leftover.pop(key):
  25. a1 = {k - {ing}: v - {alg} for k, v in leftover.items()}
  26. a2 = known + [(ing, alg)]
  27. yield from recurse(a1, a2)
  28. def valid(mapping):
  29. return all(mapping[a] in fs for fs, als in recipes.items() for a in als)
  30. cleaned_up = {v: k - clean for k, v in recipes.items()}
  31. maps, = (maps for maps in recurse(cleaned_up) if valid(maps))
  32. print(','.join(v for k, v in sorted(maps.items())))