2012-09-09 124 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) 
    .