Проверка, унифицируется ли список переменных со списком списков, содержащих буквы

У меня есть этот предикат spaces_uni(Spc,LstWords), Spc — это список переменных, таких как [X,Y,Z] или [a,Y,Z], а LstWords — это список слов, таких как [[o,r,a,n,g,e],[a,p,p,l,e],[b,a,n,a,n,a]].

Цель этого предиката — проверить, есть ли в LstWords слово, которое может унифицироваться с данным Spc.

Пример:

?- Words = [[a,m,e,n,o],[a,t,o],[d,a,o],[d,r,a,m,a],[m,a,e],[m,a,n,d,e],[s,e,d,e],[s,o,a,r]], Space = [d,A,B,C,D], spaces_uni(Space,Words).
true.

Так почему же вывод истинный, простой, потому что слово драма объединяется с [d,A,B,C,D] и становится [d,r,a,m,a]. Проблема в том, что моя программа вместо этого возвращает false, и я не понимаю, почему.

Программа:

spaces_uni(E,[P|R]) :-
                         length(E,CE),
                         length(P,CP),
                         CE \== CP,!,
                         spaces_uni(E,R).

spaces_uni(E,[P|R]) :-
                           length(E,CE),
                           length(P,CP),
                           CE == CP,!,
                           P \= E,
                           spaces_uni(E,R).


spaces_uni(E,[P|_]) :-
                         length(E,CE),
                         length(P,CP),
                         CE == CP,
                         {}/(P = E),!,
                         true.

На самом деле любая помощь будет оценена по достоинству.


person Martim Correia    schedule 24.04.2020    source источник


Ответы (1)


Какую реализацию Пролога вы используете и откуда вы взяли цель {}/(P = E)?

Унификация Пролога уже прекрасно справляется с объединением списков:

?- [d, A, B, C, D] = [d, r, a, m, a].
A = r,
B = D, D = a,
C = m.

?- [x, A, B, C, D] = [d, r, a, m, a].
false.

Итак, все, что вам нужно сделать, это написать предикат, который будет успешным, если список унифицируется с одним элементом списка списков.

Что-то типа:

word_words(Word, [Word | _Words]).
word_words(Word, [_Word | Words]) :-
    word_words(Word, Words).

Что работает следующим образом:

?- Words = [[a,m,e,n,o],[a,t,o],[d,a,o],[d,r,a,m,a],[m,a,e],[m,a,n,d,e],[s,e,d,e],[s,o,a,r]], Space = [d,A,B,C,D], word_words(Space, Words).
Words = [[a, m, e, n, o], [a, t, o], [d, a, o], [d, r, a, m, a], [m, a, e], [m, a, n|...], [s, e|...], [s|...]],
Space = [d, r, a, m, a],
A = r,
B = D, D = a,
C = m ;
false.

Но нам даже не нужно определять собственный предикат word_words/2. Он не делает ничего конкретного со словами, и он мог бы выглядеть более знакомым, если бы мы переименовали некоторые вещи:

member_list(X, [X | _List]).
member_list(X, [_Y | List]) :-
    member_list(X, List).

Это всего лишь предикат, выражающий принадлежность к списку. Таким образом, нам вообще не нужно писать какие-либо определения предикатов, мы можем просто использовать существующие предикаты членства, которые, вероятно, поставляются с вашей реализацией Prolog:

?- Words = [[a,m,e,n,o],[a,t,o],[d,a,o],[d,r,a,m,a],[m,a,e],[m,a,n,d,e],[s,e,d,e],[s,o,a,r]], Space = [d,A,B,C,D], member(Space, Words).
Words = [[a, m, e, n, o], [a, t, o], [d, a, o], [d, r, a, m, a], [m, a, e], [m, a, n|...], [s, e|...], [s|...]],
Space = [d, r, a, m, a],
A = r,
B = D, D = a,
C = m ;
false.

?- Words = [[a,m,e,n,o],[a,t,o],[d,a,o],[d,r,a,m,a],[m,a,e],[m,a,n,d,e],[s,e,d,e],[s,o,a,r]], Space = [d,A,B,C,D], memberchk(Space, Words).
Words = [[a, m, e, n, o], [a, t, o], [d, a, o], [d, r, a, m, a], [m, a, e], [m, a, n|...], [s, e|...], [s|...]],
Space = [d, r, a, m, a],
A = r,
B = D, D = a,
C = m.
person Isabelle Newbie    schedule 25.04.2020