В копилку, отличная задача для теста на собеседованиях )) Мой вариант работает на postgresql:
WITH RECURSIVE
serie(i) AS (SELECT generate_series (1, 5)),
permutate AS (SELECT ARRAY[i] p FROM serie UNION ALL SELECT p || i FROM permutate, serie WHERE i<>ALL(p)),
permatations AS (SELECT p FROM permutate WHERE array_length(p, 1)=5),
names(Winslow, Marcolla, Contee, Natsiou, Finch) AS (SELECT p[1], p[2], p[3], p[4], p[5] FROM permatations),
colors(blue, white, red, purple, green) AS (SELECT p[1], p[2], p[3], p[4], p[5] FROM permatations),
homelands(Morley, Fraeport, Dunwall, Serkonos, Bailton) AS (SELECT p[1], p[2], p[3], p[4], p[5] FROM permatations),
drinks(whiskey, coctail, absinthe, cider, rum) AS (SELECT p[1], p[2], p[3], p[4], p[5] FROM permatations),
items(cigar_case, pendant, ring, diamond, medallion) AS (SELECT p[1], p[2], p[3], p[4], p[5] FROM permatations),
matching AS (
SELECT ROW_NUMBER() OVER () solution_no, * FROM names, colors, homelands, drinks, items
WHERE Winslow = blue
AND Marcolla = 1
AND Marcolla+1 = white
AND red = purple-1
AND red = whiskey
AND Morley = green
AND cigar_case IN (Morley-1, Morley+1)
AND Finch = pendant
AND Fraeport = ring
AND diamond IN (Dunwall-1, Dunwall+1)
AND coctail IN (Dunwall-1, Dunwall+1)
AND Contee = absinthe
AND Serkonos = cider
AND rum = 3
AND Natsiou = Bailton
)
--в принципе, задача уже решена, дальнейший код для наглядного вывода результата
SELECT solution_no, value chair, string_agg(KEY, ', ') FROM matching
JOIN LATERAL json_each_text(row_to_json(matching.*)) name_pair ON key<>'solution_no'
GROUP BY solution_no, value
ORDER BY solution_no, value
Основная идея, что по каждому из признаков (имя, цвет, предмет...) имеем 120 перестановок, а общее количество комбинаций 120^5. Создаём таблицу перестановок для каждого признака, "перемножаем" их, получаем общую таблицу на 20kkk строк. Колонки - значения признаков (Конти, синий, портсигар ...), в ячейках - номер стула. Дальше условия отбора сводятся к сравнению номера стула: Уинслоу = синий, красный = виски, ром = 3... Коротко и наглядно
В копилку, отличная задача для теста на собеседованиях ))
Мой вариант работает на postgresql:
Основная идея, что по каждому из признаков (имя, цвет, предмет...) имеем 120 перестановок, а общее количество комбинаций 120^5. Создаём таблицу перестановок для каждого признака, "перемножаем" их, получаем общую таблицу на 20kkk строк. Колонки - значения признаков (Конти, синий, портсигар ...), в ячейках - номер стула. Дальше условия отбора сводятся к сравнению номера стула: Уинслоу = синий, красный = виски, ром = 3... Коротко и наглядно