Загадка Эйнштейна SQL-запросом

exp98
Дата: 15.06.2017 12:38:54
Задачу подсказали в соседней теме. Это т.н. задача (загадка) Эйнштейна, там где 6 категорий по 5 значений в каждой и 15 ограничений на них.
Сходу не получилось, остаётся 592 записи. Может и подход другой надо, идея была оставить только правильные записи.
Мои исходные данные (оракл), но может кто лучше организует
+
With country as
    (select 1 as cnt_id, 'datch' as country  from dual
        union
    select 2 as cnt_id, 'norv' as country from dual
        union
    select 3 as cnt_id, 'sweed' as country from dual
        union
    select 4 as cnt_id, 'brit' as country from dual
        union
    select 5 as cnt_id, 'germ' as country from dual
    ),

    animal as
    (select 1 as an_id, 'fish' as animal  from dual
        union
    select 2 as an_id, 'dog' as animal from dual
        union
    select 3 as an_id, 'cat' as animal from dual
        union
    select 4 as an_id, 'bird' as animal from dual
        union
    select 5 as an_id, 'horse' as animal from dual
    ),

    cigar as
    (select 1 as ci_id, 'dunhi' as cigar  from dual
        union
    select 2 as ci_id, 'marlbo' as cigar from dual
        union
    select 3 as ci_id, 'rothma' as cigar from dual
        union
    select 4 as ci_id, 'PalMal' as cigar from dual
        union
    select 5 as ci_id, 'PhilMor' as cigar from dual
    ),

    color as
    (select 1 as col_id, 'yel' as color  from dual
        union
    select 2 as col_id, 'red' as color from dual
        union
    select 3 as col_id, 'blue' as color from dual
        union
    select 4 as col_id, 'gree' as color from dual
        union
    select 5 as col_id, 'whit' as color from dual
    ),

    address as
    (select 1 as ad_id, '1' as address  from dual
        union
    select 2 as ad_id, '2' as address from dual
        union
    select 3 as ad_id, '3' as address from dual
        union
    select 4 as ad_id, '4' as address from dual
        union
    select 5 as ad_id, '5' as address from dual
    ),

    drink as
    (select 1 as dr_id, 'tea' as drink  from dual
        union
    select 2 as dr_id, 'milk' as drink from dual
        union
    select 3 as dr_id, 'water' as drink from dual
        union
    select 4 as dr_id, 'beer' as drink from dual
        union
    select 5 as dr_id, 'cafe' as drink from dual
    ),

    mixx as  -- Декартово произведение
    (select *
    from country cnt, animal an, cigar ci, color col , address ad, drink dr ) -- count=15625

select  count( m.country) from mixx m ;

+ Условия задачи
Из вики
    На одной улице подряд стоят пять домов, каждый — своего цвета. 
В каждом живёт человек, все пять — разных национальностей. 
Каждый человек предпочитает уникальную марку сигарет, напиток и домашнее животное. 
Кроме того:

 1        Норвежец живёт в первом доме.
 2        Англичанин живёт в красном доме.
 3        Зелёный дом находится слева от белого, рядом с ним.
 4        Датчанин пьёт чай.
 5        Тот, кто курит Marlboro, живёт рядом с тем, кто выращивает кошек.
 6        Тот, кто живёт в жёлтом доме, курит Dunhill.
 7        Немец курит Rothmans.
 8        Тот, кто живёт в центре, пьёт молоко.
 9        Сосед того, кто курит Marlboro, пьёт воду.
10        Тот, кто курит Pall Mall, выращивает птиц.
11        Швед выращивает собак.
12        Норвежец живёт рядом с синим домом.
13        Тот, кто выращивает лошадей, живёт в синем доме.
14        Тот, кто курит Phillip Morris, пьет пиво.
15        В зелёном доме пьют кофе.

    Вопрос:

        Кто разводит рыбок?

Модератор: Добавил условия
Dima T
Дата: 15.06.2017 13:01:11
ИМХО в декартово произведение надо добавить условия которые по строке проверяются
например "Датчанин имеет кота", "Норвежец курит данхил"
mixx as ... where (country = 'datch' or animal != 'cat') and (country = 'norv' and cigar != 'dunhi') ...

дальше проверять условия на соседство "немец справа от собаки"
select A.* from mixx A join mixx B on (A.country = 'germ' and B.animal = 'dog' and A.address > B.address) or (...)
exp98
Дата: 15.06.2017 13:07:35
Не-не-не, я эти выборки потом делаю. У меня пока затык в закономерностях типа "значения не совпадают" ну и в других неявных.
Dima T
Дата: 15.06.2017 13:10:54
Сомневаюсь. У тебя address строка, как ты на соседство сравниваешь? Поле числовое должно быть.
Dima T
Дата: 15.06.2017 13:13:50
exp98
У меня пока затык в закономерностях типа "значения не совпадают" ну и в других неявных.

Пример дай как в условии написано.
exp98
Дата: 15.06.2017 13:35:27
Вообще-то я использую по типу
to_number( '2') +- 1 == по-соседству,
хотя позднее ввёл ИДшники.
А номера друг с дргуом прекрасно и строками сравниваются.

Пример ?
Ну там типа "каждый живёт отдельно, цвета у всех разные, все курят разное и т.п." - это спрашивал, или полностью мой текст вместе с ограничениями?
А неявные, например, НОрвежец живёт в '1', при этом по-соседству с синим домом.
Dima T
Дата: 15.06.2017 13:44:16
exp98
А неявные, например, НОрвежец живёт в '1', при этом по-соседству с синим домом.

Такого нет в обычной постановке. Это два условия и проверять отдельно: на первом шаге "Норвежец живёт в '1'" на втором "Норвежец живёт по-соседству с синим домом"
exp98
Ну там типа "каждый живёт отдельно, цвета у всех разные, все курят разное и т.п." - это спрашивал, или полностью мой текст вместе с ограничениями?

Похоже я это упустил. Надо еще как-то проверить что повторов нет. Надо подумать. Это будет третий шаг.
exp98
Дата: 15.06.2017 13:48:17
Ну да, это 2-е и 12-е условие. Путём умозаключения, т.е. неявно, и приводят к полезному выводу.
exp98
Дата: 15.06.2017 13:51:57
Dima T
Похоже я это упустил. Надо еще как-то проверить что повторов нет
Вот и я тоже упустил. Возможно, что сам подход нужно менять.
Dima T
Дата: 15.06.2017 14:05:11
exp98
Dima T
Похоже я это упустил. Надо еще как-то проверить что повторов нет
Вот и я тоже упустил. Возможно, что сам подход нужно менять.

Похоже среди твоих 592 есть 5 с правильным ответом. Т.е. надо как-то из 592 проверить все комбинации по 5, а это 7.15*1013 комбинаций. Многовато чтобы тупо перемешивать :(