无法理解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).
无法理解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).
实际上,有一个内置的库进行排序,所有为你,称为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
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元素都已经被处理,和的情况。
尝试这样的事情,使用内建member/2
和setof\3
:
set_intersection(As , Bs , Xs) :-
set_of(X , (member(X,As) , member(X,Bs)) , Xs)
.
应该注意的是,如果列表As
和Bs
没有共同的元素,这将失败。另一种方法是使用findall/3
而不是set_of/3
。 findall/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)
.
我得到一个错误说“list_to_ord_set/2不存在” ...... – user1657568
你加载库? use_module(library(ordsets))加载它 – WhaleFanny