2012-09-09 164 views
0

無法理解Prolog如何工作。我試圖編寫一個規則,將三個整數列表作爲輸入(代表集合),並將屬於第一個和第二個列表的整數放入第三個列表中。SICStus Prolog列表

例子:

?-inter([10,20,30,40],[10,50,40,60], List3) 
List3 = [10, 40] 

到目前爲止,我有這個,如果一個列表包含特定字母可以識別:

mymember(X,[X|T]). 
mymember(X,[H|T]) :- mymember(X,T). 

回答

1

實際上,有一個內置的庫進行排序,所有爲你,稱爲ordsets。

inter(X, Y, Z) :- 
    list_to_ord_set(X, L1), 
    list_to_ord_set(Y, L2), 
    ord_intersection(L1, L2, Z). 

使用您的示例輸入您會收到以下

| ?- inter([10,20,30,40],[10,50,40,60],X). 
X = [10,40] ? ; 
no 
+0

我得到一個錯誤說「list_to_ord_set/2不存在」 ...... – user1657568

+0

你加載庫? use_module(library(ordsets))加載它 – WhaleFanny

0

inter(Xs, Ys, Zs)將是真正的當ZS每個元素也爲兩個X 在伊蘇。

但Zs是未知的,那麼需要更具建設性的方法。 它在這裏:iterate on Xs and store in Zs each element that is in Ys

迭代的例子是mymember/2,你可以看到它需要一個遞歸謂詞。 上述語句的另一個慣用部分是store in Zs,使用模式匹配,Prolog有一種奇特的方式來做這種事情。

inter([X|Xs], Ys, [X|Zs]) :- 
    mymember(X, Ys), inter(Xs, Ys, Zs). 

你將需要完成幀間/ 3與其它2個子句:其中X是伊蘇的部件底座遞歸,即,當全部的X元素都已經被處理,和的情況。

0

嘗試這樣的事情,使用內建member/2setof\3

set_intersection(As , Bs , Xs) :- 
    set_of(X , (member(X,As) , member(X,Bs)) , Xs) 
    . 

應該注意的是,如果列表AsBs沒有共同的元素,這將失敗。另一種方法是使用findall/3而不是set_of/3findall/3將手回空單,而不是失敗,如果我們的目標是不滿意:

set_intersection(As , Bs , Xs) :- 
    findall(X , (member(X,As) , member(X,Bs)) , Xs) 
    . 

然而findall/3返回(允許重複),而不是設置(不允許重複),所以如果你的兩個源列表不是集合,你不會得到一個集合。

member/2是一個內置的謂詞,它統一了其第一個參數與列表—的

member(X,[X|_). 
member(X,[_|Xs) :- member(X,Xs) . 

而且,最後等價的元素,如@chac在他的回答指出,可以遞歸遍歷列表。

set_intersection([] , _ , []) .   % the intersection of the empty set with anything is the empty set. 
set_intersection([A|As] , Bs , [A|Xs]) :- % if the list is non-empty, 
    member(A,Bs) ,        % - and A is a member of the 2nd set 
    ! ,          % - we cut off alternatives at this point (deterministic) 
    set_intersection(As , Bs , Xs)   % - and recurse down on the tail of the list. 
    . 
set_intersection([_|As] , Bs , Xs) :-  % if the list is non-empty, and A is NOT a embmer of the 2nd set 
    set_intersection(As , Bs , Xs)   % we just recurse down on the tail of the list. 
    . 

@ CHAC的技術,因爲他去構建結果列表,像:

[a|X] 
[a,b|X] 
[a,b,c|X] 

最終的統一,空單的特殊情況下統一列表中未結合的尾部[]使列表完成,所以最終[a,b,c|X]變成

[a,b,c] 

有點prolog魔術。這可能是比較容易理解的替代方法是使用一個工人謂語用蓄電池:

% 
% set_intersection/3: the public interface predicate 
% 
set_intersection(As , Bs , Xs) :- 
    set_intersection(As , Bc , [] , T) % we seed our accumulator with the empty list here 
    . 


% 
% set_intersection/4: the private worker bee predicate 
%  
set_intersection([]  , _ , T , Xs) :- % since our accumulator is essentially a stack 
    reverse(T,Xs)        % we need to reverse the accumulator to 
    .           % put things in the expected sequence 
set_intersection([A|As] , Bs , T , Xs) :- 
    member(A, Bs) , 
    ! , 
    T1 = [A|T] , 
    set_intersection(As , Bs , T1 , Xs) 
    . 
set_intersection([_|As] , Bs , T , Xs) :- 
    set_intersection(As , Bs , T , Xs) 
    .