2013-04-10 25 views
2

我想通過在給定列表(而不是一個)中選擇多個元素來改進select/3。例如,如果我在此列表中選擇X = 1Y = 2[1,2,3],那麼結果將是[3]改進ProLog中的select/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([],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). 

我想我必須以某種方式使用,而不是成員方法的交叉方法。

有人可以幫我嗎?

回答

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以上或SWI內置intersection/3會產生這樣的。這是有道理的,他們爲什麼不會這樣做:沒有辦法根據它們的交集來了解這兩組數據的內容,因爲這些數據根本無法存活。

+0

非常感謝Daniel Lyons。這非常有幫助! – ben 2013-04-10 16:56:25

+0

沒問題,希望你喜歡使用Prolog。 :) – 2013-04-10 17:26:16