Используя предикат выбора Пролога?

Я пытаюсь создать программу, в которой seat(Guests, Seating) удерживается, если люди в списке «Гости» могут быть перегруппированы в список «Размещение», чтобы каждый из них был совместим с теми, кто находится по обе стороны.

У меня есть факты для каждого человека:

topics(neil, [diving, football, computers, hockey]).

и т.д...

У меня также есть общий предикат - правило, которое проверяет, есть ли у двух людей общая тема.

common(Person1, Person2, Topic)

Мне придется использовать встроенный предикат выбора и мой общий предикат, определенный пользователем, но я не уверен, как это сделать.

Может кто-нибудь предоставить подходящее решение или объяснение, пожалуйста?


person Ciphor    schedule 20.03.2013    source источник


Ответы (1)


Предполагая, что у вас не обязательно иметь общие темы между первым и последним человеком в списке рассылки, вы можете:

  • Выберите одного гостя из списка «Гости», это также приведет к появлению списка рассадки без этого выбранного гостя.
  • Вызовите рекурсивную процедуру, которая берет этого гостя и выбирает другого гостя (снова возвращая списки оставшихся гостей), и проверяет совместимость. Если они совместимы, вызовите эту процедуру рекурсивно с новым гостем.
  • Базовый случай этой процедуры - когда в списке гостей больше нет гостей.

Это выглядело бы примерно так:

seats(Guests, [Person1|Seating]):-
  select(Person1, Guests, NGuests),  
  seats1(Person1, NGuests, Seating).

seats1(_, [], []).
seats1(LPerson, Guests, [RPerson|Seating]):-
  select(RPerson, Guests, NGuests),
  common(LPerson, RPerson, _),  % There is a common topic between them
  seats1(RPerson, NGuests, Seating).
person gusbro    schedule 20.03.2013
comment
Чтобы уточнить: способ, которым это работает, заключается в том, что select/3 выберет элемент из списка (начиная с первого), и если этот путь в дереве решений завершится неудачно, при возврате select выберет следующий элемент из списка и выполнит поиск решение будет продолжено оттуда. - person ; 20.03.2013
comment
@ Борис, правильно !. select/3, как здесь используется (с неустановленными первым и третьим аргументами и созданным экземпляром второго аргумента), возьмет один элемент из списка второго аргумента (объединяя его с первым аргументом) и объединит третий аргумент с остальными элементами списка . При обратном отслеживании он будет проверять все остальные элементы списка (второй аргумент select/3). Конечно, вы также можете вызвать места со вторым экземпляром списка, чтобы проверить, совместим ли список рассадки с некоторыми списками гостей. - person gusbro; 20.03.2013