将一个列表的元素与prolog中另一个列表的元素进行比较

时间:2014-03-24 16:28:22

标签: list recursion prolog

首先,我完全是Prolog的初学者。

我试图将列表的每个元素与另一个列表的每个元素进行比较。通过比较,我的意思是将这两个元素发送到我写的谓词(冲突)。到目前为止,我得到了这个:

%iterate over the first list
cmp_list([],_,_).
cmp_list([X|Y],[A|B],Result):-
      cmp_list_inner(X,[A|B],Result),
      cmp_list(Y,[A|B],Result).

%iterate over the second list
cmp_list_inner(_,[],_).
cmp_list_inner(X,[A|B],S):-
    not(conflicts(X,A)), %compare
    cmp_list_inner(X,B,[X-A|S]).%if okay, add their combination, i.e X-A to the main list which will be returned

谓词cmp_list代表外部列表的递归,而内部代表内部列表。 cmp_list(firstlist,secondlist,将返回组合后的新列表。)

这不起作用!即使它将第一个值中的单个元素的值添加到主列表中,它也不会将第二个比较(对于第一个列表中的第二个元素)附加到将返回的主列表。结果应采取以下形式: [X1-Y1],[X1-Y2],[X2-Y1],[X2-Y2] ....其中Xs来自第一个列表,Ys来自第二个列表。

任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:1)

你只需要一个简单的谓词:

cmp_list([], [], []).              % cmp_list succeeds for two empty lists
cmp_list([H1|T1], [H2|T2], [H1-H2|R]) :-
    % cmp_list of [H1|T1] and [H2|T2] succeeds if...
    \+ conflicts(H1, H2),          % conflicts fails for H1 and H2
    cmp_list(T1, T2, R).           % cmp_list succeeds for T1 and T2, result R

% Otherwise, cmp_list fails (e.g., lists are diff length)

更紧凑的是使用内置谓词maplist

cmp_list(L1, L2, R) :-                % cmp_list succeeds on L1, L2 if...
    maplist(no_conflicts, L1, L2, R). % no_conflicts succeeds for every
                                      %   corresponding pair of L1, L2 elements

no_conflicts(X, Y, X-Y) :- \+ conflicts(X-Y).

如果您只想捕获所有不会发生冲突并且忽略其余对的对,那么:

cmp_list([], _, []).
cmp_list([_|_], [], []).
cmp_list([H1|T1], [H2|T2], R) :-
    (   conflicts(H1, H2)
    ->  cmp_list(T1, T2, R)
    ;   R = [H1-H2|R1],
        cmp_list(T1, T2, R1)
    ).

这使用" if-then-else" Prolog中的模式是通过将->;分组而形成的。这将创建一个看起来像[x1-y1, x3-y3, ...]的结果。您可以通过更改以下行来选择要形成结果元素:

R = [H1-H2|R1]

例如,R = [[H1,H2]|R1]会产生类似[[x1,y1], [x3,y3], ...]的结果。

<小时/> 对于更一般的问题( ie ,你真正想要的那个:)),我将从原始代码开始,但在需要的地方修改它:

%iterate over the first list
cmp_list([], _, []).
cmp_list([X|T], L2, Result):-
    cmp_list_inner(X, L2, R1),
    cmp_list(T, L2, R2),
    append(R1, R2, Result).

%iterate over the second list
cmp_list_inner(_, [], []).
cmp_list_inner(X, [A|B], R) :-
    (   conflicts(X, A)
    ->  cmp_list_inner(X, B, R)
    ;   R = [X-A|T],
        cmp_list_inner(X, B, T)
    ).