21_allergens.py 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. #!/usr/bin/env python3
  2. import sys
  3. def parse(f):
  4. for line in f:
  5. ingredients, allergens = line[:-2].split(' (contains ')
  6. yield ingredients.split(), allergens.split(', ')
  7. def allergen_candidates(foods):
  8. candidates = {}
  9. known = set()
  10. for ingredients, allergens in foods:
  11. unknown = set(ingredients) - known
  12. for a in allergens:
  13. cand = candidates.get(a, None)
  14. if not cand:
  15. cand = candidates[a] = set(unknown)
  16. elif len(cand) > 1:
  17. cand &= unknown
  18. if len(cand) == 1:
  19. known |= cand
  20. unknown -= cand
  21. return candidates
  22. def count_safe(foods, candidates):
  23. maybe_unsafe = set.union(*candidates.values())
  24. return sum(len(set(ing) - maybe_unsafe) for ing, _ in foods)
  25. def translate_allergens(foods, candidates):
  26. unsafe = {}
  27. while candidates:
  28. found = {c.pop(): a for a, c in candidates.items() if len(c) == 1}
  29. unsafe.update(found)
  30. known = set(found)
  31. candidates = {a: c - known for a, c in candidates.items() if c}
  32. return sorted(unsafe, key=unsafe.__getitem__)
  33. foods = list(parse(sys.stdin))
  34. candidates = allergen_candidates(foods)
  35. print(count_safe(foods, candidates))
  36. print(','.join(translate_allergens(foods, candidates)))