Пролог вычитания унификации - PullRequest
1 голос
/ 28 февраля 2012

Я пытаюсь вычесть один список из другого в прологе.В моей программе во входном списке есть пробелы (например, [1,2, _, 4])

Я получаю следующий вывод:

?- subtract([1,2,3,4],[3,4,_],L).

L = [2].

, когда мне нужен выводбыть

L = [1,2].

Итак, мой вопрос, как я могу предотвратить объединение пробелов с другими элементами?Застрял на этом некоторое время.

Ответы [ 3 ]

1 голос
/ 28 февраля 2012

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

listWOblanks( [], [] ).
listWOblanks( [H|T], Tx ) :- var(H), !,  listWOblanks( T, Tx ).
listWOblanks( [H|T], [H|Tx] ) :- listWOblanks( T, Tx ).

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

0 голосов
/ 01 марта 2012

Другой способ:

% Uses list catenation to generate sublists /subtraction
conc([], L, L).

conc([X|L1], L2, [X|L3]) :-
    conc(L1, L2, L3).

% Finds all list members that have values and then
% use list catenation to generate the sublists
subtract(L1, L2, L3) :-
   findall(D, (nth0(N, L2, D), nonvar(D)), PureL2),
   conc(L3, PureL2, L1).

Предполагается, что только один список имеет '_', но вы можете сделать один и тот же поиск для L1, если оба списка имеют одну и ту же проблему.

0 голосов
/ 29 февраля 2012

larsmans является правильным, _ - это анонимная переменная , и определение lists:subtract/3 (которое, как я полагаю, вы используете в SWI-Prolog) всегда объединит их с землейсписок членов из-за его определения с использованием memberchk/2.

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

subtract2([], _, []) :- !.
subtract2([A|C], B, D) :-
    var_memberchk(A, B), !,
    subtract2(C, B, D).
subtract2([A|B], C, [A|D]) :-
    subtract2(B, C, D).

Обратите внимание, что subtract2/3 здесь почти совпадает с определением lists:subtract/3 (попробуйте listing(subtract)., чтобы убедиться в этом).Единственное отличие - это предикат членства в списке, var_memberchk/2, который определяется следующим образом:

var_memberchk(A0, [A1|_]) :- 
    A0 == A1, !.
var_memberchk(A0, [_|R]) :- 
    var_memberchk(A0, R).

Этот параметр проверяет, есть ли переменная, атом или термин в списке.Итак, попробовав это, мы получим:

?- subtract2([1,2,3,4],[3,4,_],L).
L = [1, 2].

Обратите внимание, что все равно работает, если мы называем переменные, как и следовало ожидать:

?- subtract2([1,2,A,3,B,4],[3,A,4],L).
L = [1, 2, B].

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

?- subtract2([1,2,_A,3,_B,4],[3,_A,4],L).
L = [1, 2, _B].

Наконец, обратите внимание, что, поскольку _ не имеет имени, subtract2/3 не будет никогда сможет сопоставить его с другим анонимнымпеременные в любом списке, например:

subtract2([1,2,_,4],[3,_,4],L).
L = [1, 2, _G415].

, где _G415 - анонимная глобальная переменная, обозначаемая _ в первом списке ввода.Вторая - это другая глобальная переменная (например, _G416), поэтому она никогда не может соответствовать анонимной переменной в первом списке.

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