[英]How to access unique pairs from a list in Prolog?
我有一个列表L = [a, b, c]
并且我想选择所有唯一的非重复对: [a, b], [a, c], [b, c]
。 如果我简单地使用成员 function,它当然会选择每个排列,所以我必须有一个谓词
pick_pair(List, X, Y) :-
member(X, List),
member(Y, List),
\+ X = Y.
为了访问成员,我使用另一个谓词将所有对收集到一个列表中
unique_pairs(List, Result) :-
findall([X, Y], pick_pair(List, X, Y), Result).
然后我才访问结果列表,但它会生成[[a, b], [a, c], [b, a], [b, c], [c, a], [c, b]]
。 我试图摆脱那些与list_to_set
已经存在的对相反的对,但是[a, b]
和[b, a]
在默认情况下不统一,所以它们被认为是不相等的,因此属于集合。 我会以某种方式需要为 function 或类似的东西超载统一。
我的问题是:
我们可以只访问列表中的对吗? 像my_pairs(X, Y, L)
这样的东西会将对元素直接分配给X
和Y
。 如果没有这样的谓词,我们如何制作唯一对的列表,以便我们可以使用member(X, List)
访问其元素?
顺便说一下,这个问题相当于得到所有长度为 2 的组合。
可以使用select
的自定义变体:
unique_pairs(L, E1, E2) :-
select_forward(E1, L, L0),
member(E2, L0).
select_forward(E, [H|T], F) :-
select_forward_(T, H, E, F).
select_forward_(T, H, H, T).
select_forward_([H|T], _, E, F) :-
select_forward_(T, H, E, F).
swi-prolog 中的结果:
?- unique_pairs([a,b,c], E1, E2).
E1 = a,
E2 = b ;
E1 = a,
E2 = c ;
E1 = b,
E2 = c ;
false.
在 Prolog 中一次生成n件m件物品的组合很容易:
combination( 0 , _ , [] ) .
combination( N , [X|Xs] , [X|Ys] ) :- N > 0, N1 is N-1, combination(N1,Xs,Ys).
combination( N , [_|Xs] , Ys ) :- N > 0, combination(N,Xs,Ys).
一旦你有了它,你的pick_pair/2
就变成了:
pick_pair( Xs, P ) :- combination(2,Xs,P) .
您还可以通过算术构造组合:您只需要传递包含变量的所需长度的列表——就是这样:
combination( _ , [] ) .
combination( [X|Xs] , [X|Ys] ) :- combination(Xs,Ys).
combination( [_|Xs] , [Y|Ys] ) :- combination(Xs,[Y|Ys]).
使用此实现,如果第二个参数完全未实例化,它将生成从 0 到源列表长度的任意长度的所有组合。 如果第一个参数未实例化......它可能会产生一组[理论上]无限的结果。
有了这个实现,你的pick_pair/2
就变成了
pick_pair( Xs, [P,Q] ) :- combination(Xs, [P,Q] ).
或者可能
pick_pair( Xs, P ) :- length(P,2), combination(Xs,P).
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.