Вы можете использовать itertools.combinations
, чтобы выбрать все большее количество предметов из всех отдельных предметов и проверить, есть ли в выбранном наборе предметов хотя бы один предмет в каждом наборе в списке:
from itertools import count, combinations
r = [{'a', 'b', 'c'},
{'c', 'd'},
{'a', 'g', 'h'},
{'d', 'e', 'f'},
{'g', 'k', 'l'}]
all_items = set.union(*r)
print(next(set(picks) for size in count(1)
for picks in combinations(all_items, size)
if all(any(i in s for i in picks) for s in r)))
Это выводит: (Ваш пример ввода имеет более одного оптимального решения и выводит только одно из них.)
{'c', 'd', 'g'}
Если вы хотите все оптимальные решения, вы можете использовать itertools.groupby
над выражением генератора выше сlen
в качестве ключевой функции:
from itertools import groupby
list(next(groupby((set(picks) for size in count(1)
for picks in combinations(all_items, size)
if all(any(i in s for i in picks) for s in r)), len))[1])
Возвращает:
[{'f', 'c', 'g'},
{'e', 'c', 'g'},
{'a', 'd', 'g'},
{'b', 'd', 'g'},
{'c', 'd', 'g'},
{'a', 'd', 'l'},
{'a', 'd', 'k'}]