在prolog中添加列表而不重复

时间:2014-04-06 01:45:28

标签: prolog

我需要知道如何在不重复的情况下将所有两个列表相互添加,如[1,2]& [3,4]结果将是[1,3] [1,4] [2,3] [2,4]

1 个答案:

答案 0 :(得分:0)

这是无法按预期运行的解决方案:

(1) comb([], [], []).
(2) comb([H|T], [X|Y], [H,X]).
(3) comb([H,T|T1], [X,Y|T2], [T,Y]).
(4) comb([H|T], [X|Y], L) :-
        comb(T, Y, [H|X]). 

(1)说,将空列表与空列表组合是一个空列表。这听起来在逻辑上是正确的。

(2)说, [H,X]是来自[H|T][X|Y] 的一对元素。这是真的(仅提供解决方案的一种组合)。

(3)说, [T,Y]是来自[H,T|T1][X,Y|T2] 的一对元素。这也是正确的(仅为解决方案提供另一种组合,与#2不同)。

(4)说, L是来自[H|T][X|Y]的一对元素,如果[H|X]是来自T的一对元素和Y 。这不可能是真的,因为L没有出现在子句的结果中,因此它永远不会用值进行实例化。

上述解决方案过度思考,比需要的更复杂。它失败了,因为它硬编码了两个解决方案(匹配前两个元素和后两个元素)。然后recursive子句出错,因为它没有逻辑基础,解决方案留作单例变量。

首先,您需要确定谓词的含义。在这个特定问题中,如果comb(Xs, Ys, P).是一对(比如P[X,Y]来自X,您可以认为谓词Xs为TRUE ( ie XXs)的成员,Y来自YsY是{Ys的成员1}})。然后,当您查询谓词时,它将提示您每个解决方案,直到找到所有解决方案。

此问题可以通过一条规则说明: [X,Y]是分别来自XsYs的元素的组合,如果X是成员的话XsY的成员是Ys 的成员。这听起来像是一个简单的真实陈述,但是你需要解决这个问题。

将其翻译成Prolog可以得到:

comb(Xs, Ys, [X,Y]) :-  % [X,Y] is combination of elements from Xs and Ys if...
    member(X, Xs),      % X is a member of Xs, and
    member(Y, Ys).      % Y is a member of Ys

现在让我们试一试:

| ?- comb([1,2],[3,4],P).

P = [1,3] ? ;

P = [1,4] ? ;

P = [2,3] ? ;

P = [2,4]

(2 ms) yes
| ?-

它找到了所有的组合。我们让Prolog完成所有工作,我们只需要声明规则是什么。

如果要在单个列表中收集所有结果,可以使用内置谓词,例如findall/3

| ?- findall(P, comb([1,2], [3,4], P), AllP).

AllP = [[1,3],[1,4],[2,3],[2,4]]

yes
| ?-

瞧瞧。 :)

您还可以非常轻松地概括解决方案,并从给定列表列表中的每个列表中选择一个元素。这里,multicomb/2作为第一个参数列出了列表(例如,[[1,2],[3,4]]`并生成每个元素组合,每个组合一个这些子列表:

multicomb([L|Ls], [X|Xs]) :-
    member(X, L),
    multicomb(Ls, Xs).
multicomb([], []).

给出了:

| ?- multicomb([[1,2],[3,4]], P).

P = [1,3] ? a

P = [1,4]

P = [2,3]

P = [2,4]

yes
| ?-

| ?- multicomb([[1,2],[a,b],[x,y,z]], P).

P = [1,a,x] ? a

P = [1,a,y]

P = [1,a,z]

P = [1,b,x]

P = [1,b,y]

P = [1,b,z]
...