無法理解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