2010-12-10 4 views
4

Я реализую вариацию в Загадке Эйнштейна, и у меня проблемы.Уникальные элементы в списке (Prolog)

При попытке вычислить решение я попробовать это:

solve(Street) :- Street = [_House1,_House2,_House3,_House4,_House5], 
%hint one goes here 
%hint two goes here 
%etc. 

Затем я могу попросить решение, набрав: решить (Street)

Однако это приходит в виде раствора:

  1. дом (цветок, еда, домашнее животное, спорт)
  2. дом (цветок, еда, домашнее животное, спорт)
  3. дом (х, продукты питание, домашнее животное, спорт)
  4. дома (цветок, еда, домашнее животное, спорт)
  5. дома (х, цветок, животное, спорт)

Как вы можете см. 2 раза x, остальные - все виды продуктов питания, цветы, домашние животные и спорт. Но каждый тип уникален: если одному человеку нравится цветок X, больше никто не может понравиться X.

Теперь, почему мое решение дает 2 x, легко увидеть: нам дают количество подсказок, но во всех намеки только упоминаются 4 цветка. Поэтому Prolog не знает, что есть еще один цветок, и просто использует x дважды, просто потому, что это возможно и выполняет все остальные намеки.

Я хочу сказать, что все типы продуктов и цветов и т. Д. На Улице уникальны, поэтому он должен оставить пустую, когда он использовал все типы уже. 3 будет выглядеть так: house(x , food, pet ,sport) и 5 будет выглядеть так: house(_, flower, pet, sport).

Я также попытался это добавление к намекам: (скажем, «Кактус» является один из цветов, не упомянутые в намеках) member(house(cactus,_,_,_), Street)

Однако тогда моя программа не заканчивается ...

Подсказка может выглядеть так: is_neighbour(house(_,_,_,football),house(_,_,fish,_), Street), с: is_neighbour(A,B,List) с true, когда A и B находятся рядом друг с другом в List. Подсказка может быть переведена на: человека, который любит футбол, рядом с человеком, у которого есть рыба.

Если вам нужна дополнительная информация, я готов разработать. :)

ответ

2

Чтобы выразить, что цветок не сообщается дважды, а также чтобы убедиться, что все цветы связаны, вы можете использовать предикат перестановки/2: список всех цветов должен быть перестановкой списка указанных цветов , Это будет читаться как [непроверенными]

flowers([], []). 
flowers([house(Flower,_,_,_)|Street], [Flower|Rest]) :- flowers(Street, Rest). 

-- ... 
    flowers(Street, Flowers), 
    permutation(Flowers, [kaktus, tulpe, nelke, rose, fingerhut]), 

Edit: 10 цветов, используя перестановки, вероятно, слишком медленно.Альтернативный подход -

flower(kaktus). 
flower(tulpe). 
flower(nelke). 
--... 

     flowers(Street,[F1,F2,F3,F4,F5,F6,F7,F8,F9,F10]), 
     flower(F1), flower(F2), F1\=F2, 
     flower(F3), F3\=F1, F3\=F2, 
     flower(F4), F4\=F1, F4\=F2, F4\=F3, 
     --... 
+0

Звучит как логический и понятный ответ, однако я должен что-то делать неправильно. Я добавил все цветы во второй список перестановок. Я также помещал 'flowers (Street, Flowers)' и перестановку 'solve (Street)'. Но теперь это, похоже, не закончится. (обычно это заканчивается в течение 5 минут, но теперь это было более 15 минут.) Неважно, где я помещаю «перестановку»? – Aerus

+0

Перестановка должна быть симметричной для обоих аргументов, поэтому замена аргументов не должна. Помещение перестановочного вызова в другом месте должно очень помочь, однако: вы должны сначала поставить те условия, которые больше всего ограничивают пространство решений. Положите в нее записи, чтобы он отслеживал, что он делает. –

+0

Когда я нахожу вызов (write()) вокруг перестановки в конце подсказок, которые он дает: перестановка ([герань, гиацинт, ** лели **, георгин, ** лели **], [кактус, лели, герань, hyacint, георгин]). Когда я помещаю его перед всеми подсказками, которые он дает мне: перестановка ([_ 46, _53, _60, _67, _74], [кактус, лели, герань, гиацинт, георгины]). Я не уверен, что это значит. Выход по-прежнему дает мне 2 x, но он заканчивается. Нужно ли мне также добавлять перестановки для других типов, чтобы эта единственная перестановка работала? – Aerus