Пролог проверяет, не равен ли первый элемент в списках и равен ли второй элемент в списке - PullRequest
0 голосов
/ 22 ноября 2018

Я хочу сравнить 2 списка, первый элемент не должен быть равен, второй должен быть равен.

пример базы данных:

likes(josh,muse).
likes(sam,muse).
likes(josh,gnr).
likes(sam, radiohead).

, поэтому он должен возвращать true для того же([Джош, Муза], [Сэм, Муза]).

Это то, что я пробовал до сих пор:

same([H1|R1], [H2|R2]):-
    H1 \= H2,
    same(R1,R2).

Это вернуло false для каждой комбинации.

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

При чтении вашего вопроса вы сначала дали базу данных фактов

likes(josh,muse).
likes(sam,muse).
likes(josh,gnr).
likes(sam, radiohead).

, но затем использовали список для предиката

same([josh,muse], [sam,muse]).

Когда Пауло ответил, начиная со списка, я отвечу, начиная со спискас фактами.

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

same_1(P1,P2,Item) :-
    likes(P1,Item),
    likes(P2,Item).

, что дает

?- same_1(P1,P2,Item).
P1 = P2, P2 = josh,
Item = muse ;
P1 = josh,
P2 = sam,
Item = muse ;
P1 = sam,
P2 = josh,
Item = muse ;
P1 = P2, P2 = sam,
Item = muse ;
P1 = P2, P2 = josh,
Item = gnr ;
P1 = P2, P2 = sam,
Item = radiohead.

Итакдля этого необходимо убедиться, что P1 не совпадает с P2.

same_2(P1,P2,Item) :-
    likes(P1,Item),
    likes(P2,Item),
    P1 \= P2.

, что дает

?- same_2(P1,P2,Item).
P1 = josh,
P2 = sam,
Item = muse ;
P1 = sam,
P2 = josh,
Item = muse ;
false.

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

Изменение кода для создания нормализованных записей.

same_3(P1,P2,Item) :-
    likes(T1,Item),
    likes(T2,Item),
    T1 \= T2,
    normalize(T1,T2,P1,P2).

normalize(P1,P2,P1,P2) :- P1 @> P2.
normalize(P1,P2,P2,P1) :- P1 @=< P2.

, который возвращает

?- same_3(P1,P2,Item).
P1 = sam,
P2 = josh,
Item = muse ;
P1 = sam,
P2 = josh,
Item = muse ;
false.

Обратите внимание, что у этого результата есть имена в том же порядке.

Теперь просто сохраните результаты по мере их создания и толькодобавить уникальные предметы к результату.Это делается с помощью setof / 3 .

?- setof((P1,P2,Item),(same_3(P1,P2,Item)),Bag).
Bag = [(sam, josh, muse)].
0 голосов
/ 22 ноября 2018

Нотация пролога [Head|Tail] для списков, которые вы используете в определении предиката same/2, обеспечивает доступ к спискам head и tail .Хвост списка сам по себе является (возможно, пустым) списком.Но в вашем случае вы хотите получить доступ к первому и второму элементам, что вы можете сделать, написав [First, Second| _] (т.е. перечислив элементы, разделенные запятой; здесь я использую анонимную переменную дляхвост, поскольку он нам не нужен, и поэтому мы можем его игнорировать).

Ваш предикат можно исправить, переписав его следующим образом:

same([F1,S1|_], [F2,S2|_]):-
    F1 \== F2,
    S1 == S2.

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

same([F1,S1], [F2,S2]):-
    F1 \== F2,
    S1 == S2.

Примеры вызовов:

?- same([josh,muse], [sam,muse]).
true.

?- same([sam,muse], [sam,muse]).
false.

?- same([josh,muse], [sam,maria]).
false.

В качестве последнего примечания, ваш вопрос о член равенства но в своей попытке решения вы используете термин унификация .Они имеют различную семантику и их не следует путать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...