Jeśli przez "koniunkcja" rozumiesz "przecięcie", powinieneś spojrzeć na implementację w SWI-Prolog library(lists)
predykatu intersection/3
. Zawiera cięcia, ale możesz je pominąć, jeśli nie masz nic przeciwko wszystkim punktom kontrolnym.
Dzięki niemu:
?- intersection([a,b,c,a],[a,v,c],I).
I = [a, c, a].
Oczywiście, to nie działa nawet w orzecznik biblioteki, bo trzeba zestawy z aktualnej definicji. (Wystarczy, że tylko pierwszy argument jest zbiorem.)
Możesz tworzyć zestawy z predykatem sort/2
: jeśli pierwszym argumentem jest lista z powtórzeniami, drugim argumentem będzie posortowana lista bez powtórzeń, na przykład :
?- sort([a,b,c,a], S1), intersection(S1, [a,v,c], I).
S1 = [a, b, c],
I = [a, c].
czy może:
?- sort([a,b,c,a], S1), intersection(S1, [a,v,c,c,a,c], I).
S1 = [a, b, c],
I = [a, c].
?- sort([a,b,c,a,b,c,a,b,c], S1), intersection(S1, [a,v,c,c,a,c], I).
S1 = [a, b, c],
I = [a, c].
Jeśli sortować oba argumenty, można użyć ord_intersection/3
z library(ordsets)
, realizowane w warunkach oset_int/3
.
?- sort([a,b,c,a], S1), sort([a,v,c,c,a,c], S2), ord_intersection(S1, S2, I).
S1 = [a, b, c],
S2 = [a, c, v],
I = [a, c].
Co ważne, oset_int/3
nie stosuje żadnych cięć w jego realizacji. Zakłada się jednak, że pierwszy i drugi argument są listami elementów posortowanych przez "standard order of terms" i bez duplikatów, jak to uczynił sort/2
.
Jeśli z jakiegoś powodu nie chcesz używać sort/2
, mógłbyś może korzystać z akumulatora i sprawdzić z nim przed podjęciem element do skrzyżowania:
my_intersection(Xs, Ys, Zs) :-
my_intersection_1(Xs, Ys, [], Zs).
my_intersection_1([], _, Zs, Zs).
my_intersection_1([X|Xs], Ys, Zs0, Zs) :-
member(X, Ys), \+ member(X, Zs0),
my_intersection_1(Xs, Ys, [X|Zs0], Zs).
my_intersection_1([_|Xs], Ys, Zs0, Zs) :-
my_intersection_1(Xs, Ys, Zs0, Zs).
oczywiście kolejność elementów w wyniku zostanie teraz odwrócony.Jeśli nie jest to, co masz na myśli przez „wspólnie”, można na przykład przerobić pierwsze dwie klauzule my_intersection_1/4
jak:
my_intersection_1([], _, _, []).
my_intersection_1([X|Xs], Ys, Zs0, [X|Zs]) :-
member(X, Ys), \+ member(X, Zs0),
my_intersection_1(Xs, Ys, [X|Zs0], Zs).
Nie jest całkowicie jasne, co masz na myśli przez "koniunkcja". Masz na myśli "skrzyżowanie"? –