2

我想通过在给定列表中选择多个元素(而不是一个)来改进序言中的select/3。例如,如果我在此列表中选择X = 1Y = 2 [1,2,3],那么结果将是[3]

这是我到目前为止所拥有的:

select_pair(X,Y,[X|Xs],Xs) :- member(Y,Xs).
select_pair(X,Y,[H|T1],[H|T2]) :- select_pair(X,Y,T1,T2).

结果是:

?- select_pair(X,Y,[1,2,3],Zs).
X = 1,
Y = 2,
Zs = [2, 3] ;
X = 1,
Y = 3,
Zs = [2, 3] ;
X = 2,
Y = 3,
Zs = [1, 3] ;

但是,正确的结果应该是 Zs = [3]、[2]、[1]。我知道我必须以某种方式将这两个值相交;因此,这里是 intersect 方法:

intersect([],M,[]).
intersect([X|L],M,[X|I]) :- member(X,M), intersect(L,M,I).
intersect([X|L],M,I) :- \+ member(X,M), intersect(L,M,I).

我想我必须以某种方式使用 intersect 方法而不是成员方法。

有人可以帮帮我吗?

4

1 回答 1

2

你这么近!使用select/3代替member/2

select_pair(X, Y, [X|Xs], Result) :- select(Y, Xs, Result).
select_pair(X, Y, [H|T1], [H|T2]) :- select_pair(X,Y,T1,T2). % unmodified

?- select_pair(X, Y, [1,2,3], Z).
X = 1,
Y = 2,
Z = [3] ;
X = 1,
Y = 3,
Z = [2] ;
X = 2,
Y = 3,
Z = [1] ;
false.

为了比较,我很想像这样编写代码:

select_pair(X, Y, In, Out) :- 
  select(X, In, Mid), select(Y, Mid, Out).

不过,这实际上会产生排列而不是组合,我推断这不是您想要的。

我不认为你将能够相交来解决这个问题。直观地说,你想做的是这样的:

select_pair(X, Y, In, Out) :- intersection([X,Y], Out, In).

问题是intersect/3上面或内置的 SWIintersection/3都不会生成那样的。他们为什么不这样做是有道理的:没有办法根据它们的交集知道两组的内容,因为这些数据根本无法生存。

于 2013-04-10T05:41:53.790 回答