С учетом всех вопросов о "отличной комбинации" и "декартовом произведении", связанных с SO, я уверен, что для этого вопроса есть название и каноническое решение, но я не собираюсь его поднимать.
Обновление ... Вот потенциально лучший пример: Предположим, в клубе регулярно проводятся лотереи. Многие вещи разыгрываются за событие, и участники покупают билеты за каждую вещь. В лотерейный вечер менеджер лотереи распечатывает пачки карточек с именами, партии A, B, C и так далее. Когда разыгрывается каждый предмет, он бросает одну из этих предварительно собранных партий в бункер, смешивает ее и рисует имя. После раздачи приза имя возвращается в партию, которую он использует повторно, если какой-либо другой предмет имеет ту же партию участников. Вопрос: существует ли алгоритм без сохранения состояния, который может собирать партии карточек с именами, печатая минимальное общее количество карточек? [Если нет, то пример HashSet <> Криса Шейна - наиболее эффективная альтернатива с отслеживанием состояния, которую я знаю.]
Оригинальный вопрос и примеры: Рассмотрим следующие списки людей, бутербродов и аллергий (хранятся реляционно; эти структуры данных предназначены только для того, чтобы публикация была короткой, и не являются неотъемлемой частью вопроса или решения) :
var people = { "Pete", "Barb", "Debbie", "Frank", "Ralph", "Sally" };
var sandwiches = { "Peanut Butter", "Egg Salad", "Tuna Salad", "Oven Roasted Chicken", "Gluten-free Twigs" };
var allergies = {
{ "Pete", null },
{ "Barb", { "Peanut Butter" } },
{ "Debbie", { "Peanut Butter", "Egg Salad", "Tuna Salad" } },
{ "Frank", { "Egg Salad", "Tuna Salad" } },
{ "Ralph", { "Oven Roasted Chicken" } },
{ "Sally", { "Egg Salad", "Tuna Salad" } } };
Чтобы найти людей, которые могут съесть тот или иной бутерброд, я, конечно, могу достаточно легко перебрать бутерброды (внешние) и людей (внутренние) и проверить на аллергию.
Однако я хочу предварительно рассчитать и опубликовать наименьший список неаллергических людей наборов , которые будут охватывать все бутерброды (люди, очевидно, будут принадлежать более чем к одному набору), не более чем один набор людей для любого сэндвича, и максимальное повторное использование, например, набор [Пит, Барб, Дебби, Фрэнк, Салли] будет охватывать как безглютеновые веточки, так и жареную курицу в духовке.
Например, скажем, есть список бутербродов, которые нужно разыграть. Повар делает один, а затем должен выяснить, кто участвует в розыгрыше (все, кто не аллергик). Я хочу получить наименее повторяющуюся пачку карточек с именами в резиновой полоске, пачку A, B, C и так далее, чтобы можно было иметь список сэндвичей, каждый из которых указывает, какую пачку карточек с именами бросить в шляпу для этого бутерброда , Представьте себе, что бумага с именной карточкой стоит действительно дорого. (Очевидно, я изменил проблемный домен для примера.)
Я делаю это сейчас, используя эквивалент хеш-таблицы наборов людей, а затем вставляю указатели на эти наборы в словарь, снабженный сэндвичем. Он работает просто отлично, но чувствует себя не элегантно.
Спасибо всем, кто может назвать эту проблему и указать мне на более симпатичный (или более учебный) подход.
Обновление : я достигаю желаемого конечного результата, используя эквивалент MySQL GROUP_CONCAT. Это не идеально, но я добавляю это, потому что это проясняет желаемый конечный результат. В псевдокоде:
// SandwichPeople = the sandwich list with a concatenated list of
// people who can eat it:
SELECT Sandwich.SandwichName, GROUP_CONCAT(Person.FullName SEPARATOR ', ') as MemberNames
FROM Sandwich JOIN Person on [...not allergic...]
// SandwichRoster = distinct People from SandwichPeople with auto id
INSERT IGNORE INTO SandwichRoster (MemberNames)
SELECT DISTINCT MemberNames from SandwichPeople
// Match sandwiches with rosters:
SELECT SandwichPeople.SandwichName, SandwichRoster.ID
FROM SandwichPeople
JOIN SandwichRoster on SandwichPeople.MemberNames = SandwichRoster.MemberNames