Използване на предиката за избор на Prolog?

Опитвам се да направя програма, в която 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