当给出列表时,我想计算列表中所有可能的对组合。
例如2)输入是一个列表(a,b,c)我想获得对(a,b)(a,c)(b,c)
例如1)输入是一个列表(a,b,c,d)我想获得对(a,b)(a,c)(a,d)(b,c)(b,d)和(c,d)
答案 0 :(得分:2)
使用 select/3
两次(或select/3
一次,member/2
一次)将允许您在此处实现您想要的效果。如果它仍然很麻烦,我会让你弄清楚细节并寻求帮助。
BTW,列表的Prolog语法不是(a, b, c)
而是[a, b, c]
(好吧,它是语法糖,但我会留下它)。
修改:正如@WillNess指出的那样,您不是要寻找任何一对(X, Y)
,而只是寻找X
之前的Y
对的对列表。
DCG非常适合:如@false所述,它们可以产生graphically appealing solution:
... --> [] | [_], ... .
pair(L, X-Y) :-
phrase((..., [X], ..., [Y], ...), L).
或者,如果你使用SWI-Prolog,对append/2
的调用也会以类似的方式解决问题,但效率低于DCG:
pair2(L, X-Y) :-
append([_, [X], _, [Y], _], L).
你可以通过@WillNess在评论中提出的基本递归来实现。如果需要,我会留下这部分给他详细说明!
答案 1 :(得分:2)
好的,所以翻译Haskell的
pairs (x:xs) = [ (x,y) | y<-xs ]
++ pairs xs
pairs [] = []
作为一个回溯的Prolog谓词,它是一个简单而简短的
pair([X|XS],X-Y):- member( ... ,XS). %% fill in the '...' here
pair([_|XS],P) :- pair(XS, ... ). %%
%% pair([],_) :- false.
要获得所有可能的对,请使用findall
:
pairs(L,PS):- findall(P, pair(L,P), PS).
如果您的列表中包含逻辑变量,请考虑使用bagof
。然而,控制bagof
的回溯可能是一个复杂的问题。
pairs
也可以写为确定性的,非回溯的递归定义,通过累加器参数构造其输出列表 - 这里以自上而下的方式,这使得它成为差异列表< / em>真的:
pairs([X|T],PS):- T=[_|_], pairs(X,T,T,PS,[]) ; T=[], PS=[].
pairs([],[]).
pairs(_,[],[],Z,Z).
pairs(_,[],[X|T],PS,Z):- pairs(X,T,T,PS,Z).
pairs(X,[Y|T],R,[X-Y|PS],Z):- pairs(X,T,R,PS,Z).
答案 2 :(得分:0)
这是解决此问题的一种可能方法。
以下谓词combine/3
为真
如果第三个参数对应于一个列表
包含对,其中每个对的第一个元素
等于combine/3
的第一个参数。
每对的第二个元素将对应一个项目
谓词combine/3
的第二个参数中的列表。
combine/3
应该如何工作的一些示例:
?- combine(a,[b],X).
X = [pair(a,b)]
?- combine(a,[b,c,d],X).
X = [pair(a,b), pair(a,c), pair(a,d)]
定义combine/3
的可能方式:
combine(A,[B],[pair(A,B)]) :- !.
combine(A,[B|T],C) :-
combine(A,T,C2), % Create pairs for remaining elements in T.
append([pair(A,B)],C2,C). % Append current pair and remaining pairs C2.
% The result of append is C.
现在combine/3
可用于定义pair/2
:
pairs([],[]). % Empty list will correspond to empty list of pairs.
pairs([H|T],P) :- % In case there is at least one element.
nonvar([H|T]), % In this case it expected that [H|T] is instantiated.
pairs(H,T,P).
pairs(A,[B],[pair(A,B)]) % If remaining list contains exactly one element,
:- !. % then there will be only one pair(A,B).
pairs(A,[B|T],P) :- % In case there are at least two elements.
combine(A,[B|T],P2), % For each element in [B|T] compute pairs
% where first element of each pair will be A.
pairs(B,T,P3), % Compute all pairs without A recursively.
append(P2,P3,P). % Append results P2 and P3 together.
样品用量:
?- pairs([a,b,c],X).
X = [pair(a, b), pair(a, c), pair(b, c)].
?- pairs([a,b,c,d],X).
X = [pair(a, b), pair(a, c), pair(a, d), pair(b, c), pair(b, d), pair(c, d)].
答案 3 :(得分:0)
您可以使用append/
遍历列表:
?- append(_,[X|R],[a,b,c,d]).
X = a,
R = [b, c, d] ;
X = b,
R = [c, d] ;
X = c,
R = [d] ;
X = d,
R = [] ;
false.
接下来,使用member/2
对X-Y
中的每个Y
组成一对R
:
?- append(_,[X|R],[a,b,c,d]), member(Y,R), Pair=(X-Y).
X = a,
R = [b, c, d],
Y = b,
Pair = a-b ;
X = a,
R = [b, c, d],
Y = c,
Pair = a-c ;
X = a,
R = [b, c, d],
Y = d,
Pair = a-d ;
X = b,
R = [c, d],
Y = c,
Pair = b-c ;
X = b,
R = [c, d],
Y = d,
Pair = b-d ;
X = c,
R = [d],
Y = d,
Pair = c-d ;
false.
然后,使用findall/3
收集列表中的所有对:
?- findall(X-Y, (append(_,[X|R],[a,b,c,d]), member(Y,R)), Pairs).
Pairs = [a-b, a-c, a-d, b-c, b-d, c-d].
因此,您的最终解决方案可以表示为:
pairs(List, Pairs) :-
findall(X-Y, (append(_,[X|R],List), member(Y,R)), Pairs).
一个使用示例是:
?- pairs([a,b,c,d], Pairs).
Pairs = [a-b, a-c, a-d, b-c, b-d, c-d].