|
| 1 | +from collections import defaultdict |
| 2 | + |
| 3 | +import numpy as np |
| 4 | +from more_itertools import flatten |
| 5 | + |
| 6 | +with open("input.txt") as f: |
| 7 | + lines = [x.strip() for x in f] |
| 8 | + |
| 9 | +foods = [x.split(" (contains ")[0].split() for x in lines] |
| 10 | +allergens = [x.split(" (contains ")[1][:-1].split(", ") for x in lines] |
| 11 | +recipe = list(zip(foods, allergens)) |
| 12 | + |
| 13 | +poss_allergens = sorted(set(list(flatten(allergens)))) |
| 14 | + |
| 15 | +poss = [] |
| 16 | +for _, pa in enumerate(poss_allergens): |
| 17 | + k = [] |
| 18 | + for fs, allergs in recipe: |
| 19 | + if pa in allergs: |
| 20 | + k.append(set(fs)) |
| 21 | + poss.append(k) |
| 22 | + |
| 23 | +reduced = [set.intersection(*ps) for ps in poss] |
| 24 | +remaining_foods = sorted(set(flatten(reduced))) |
| 25 | +count = len([f for f in flatten(foods) if f not in remaining_foods]) |
| 26 | +print(count) |
| 27 | +poss_mat = np.array([[1 if r in red else 0 for r in remaining_foods] for red in reduced]) |
| 28 | + |
| 29 | +change = True |
| 30 | +seen = set() |
| 31 | +while change: |
| 32 | + change = False |
| 33 | + for i, row in enumerate(poss_mat): |
| 34 | + if sum(row) == 1 and i not in seen: |
| 35 | + seen.add(i) |
| 36 | + change = True |
| 37 | + col = np.argmax(row) |
| 38 | + poss_mat[:, col] = 0 |
| 39 | + poss_mat[i, col] = 1 |
| 40 | + |
| 41 | +print(",".join(remaining_foods[np.argmax(poss_mat[i])] for i in range(len(remaining_foods)))) |
0 commit comments