プロローグで2つのリストが同じ要素を持っているかどうかを判断する方法は? リストAとBの2つのリストがある場合、それらが同じ要素を持っているかどうかを知りたいです。
5 に答える
述語を書く必要があります。member/2
おそらくprologビルトインが役に立つでしょう。
答えを出さずにこれ以上言うのは難しいです。ちょっと考えてみてください。あなたはそれを得るでしょう。
を使用してはintersection/3
どうですか?
doesIntersect(X,Y) :-
intersection(X,Y,Z),
dif(Z,[]).
intersection/3
が空のリストを生成する場合、リストには共通点がなく、結果は false です。
intersection/3
member/2
再帰的に呼び出します:
intersection([X|Tail],Y,[X|Z]) :-
member(X,Y),
intersection(Tail,Y,Z).
intersection([X|Tail],Y,Z) :-
\+ member(X,Y),
intersection(Tail,Y,Z).
intersection([],_,[]).
組み込みの predicate に基づく純粋な実装から始めmember/2
ます。
common_member(Xs,Ys) :-
member(E,Xs),
member(E,Ys).
サンプルクエリ:
?- common_member([1,2,3],[1]).
true
; false.
?- common_member([1,2,3],[4]).
false.
?- common_member([1,2,3],[2,3,1]).
true
; true
; true
; false.
宣言的には、上記のコードは問題ありません。ただし、成功すると無駄な選択肢が残ります。また、両方のリストに複数のアイテムが存在する場合、冗長な回答が得られます。
論理的に純粋な状態を保ちながら、上記の効率面を改善できますか? はい!
しかし、どのように?if_/3
具体化されたテスト述語と一緒に使用することでmemberd_t/3
!
common_memberd([X|Xs],Ys) :-
if_(memberd_t(X,Ys), true, common_memberd(Xs,Ys)).
上記のサンプル クエリをもう一度実行してみましょう。今回は次のようにしcommon_memberd/2
ます。
?- common_memberd([1,2,3],[1]).
true.
?- common_memberd([1,2,3],[4]).
false.
?- common_memberd([1,2,3],[2,3,1]).
true.
冗長な回答は排除され、後続のクエリは決定論的にそうします。
common_memberd/2
は純粋であるため、非常に一般的なクエリに対しても適切な回答が得られることに注意してください。
?- common_memberd([1,2,3],[A,B]).
A=1
; dif(A,1), B=1
; A=2 , dif(B,1)
; dif(A,1), dif(A,2), B=2
; A=3 , dif(B,1), dif(B,2)
; dif(A,1), dif(A,2), dif(A,3), B=3
; false.
differs/2
リストのいずれかの要素がリストのA
メンバーでないかどうかを検証する述語を作成することから始めることができますB
。A
この条件を満たす要素を に見つけることができれば、A
に含まれていないと断言できますB
。A
のすべての要素がに存在することを確認しようとする方が実際には簡単ですB
。
組み込みの predicate を使用するとmember/2
、次のdiffers/2
ようになります。
differs(T, Q):-
member(X,T),
not( member(X, Q)).
両方のリストに同じ要素が含まれていることを証明するには、含まれていないことを確認する必要がありますdiffers
。@repeat で使用されているのと同じ述語名を使用して (興味深いことに、今繰り返すのは誰ですか?)、これが私のcommon_memberd\2
述語です。
common_memberd(T, Q):-
not( differs(T, Q)),
not( differs(Q, T)).
相談:
?- common_memberd( [2,3,4,1], [3, 1,4,2]).
true.
?- common_memberd( [2,3,1,5], [3, 1,4,2]).
false.
注: この解決策は、要素の順序に関係なく、または要素が重複しているかどうかに関係なく機能します。
これがあなたが探しているものかどうか教えてください:
same(T, Q) :- any(T, Q), !; any(Q, T), !.
any([X|_], [X,_]):- !.
any([X|T], Q) :- member(X, Q), !; any(T, Q), !.
あなたがそれを参照する場合:
?- same([1,2,3,4], [3]).
true.
?- same([1,2,3,4], [4]).
true.
?- same([1], [1,4]).
true.
?- same([1,4], [1]).
true.