An item is displayed exactly once in the list in Prolog

I want to write a predicate that checks if an item appears only once in the list.

once(Element, List).

My code is:

once(X, [H | T]) :-
    \+ X = H,
    once(X, T).
once(X, [X | T]) :-
    \+ member(X, T).

?- once(c, [b,a,a,c,b,a]).
true

?- once(b, [b,a,a,c,b,a]).
false.

But if I ask:

once(X, [b,a,a,c,b,a]).

Prolog Answers:

false

Why? Prolog should find the solution X = c. Where is the mistake?

+4
source share
2 answers

Running a tracein the prolog can be very useful in determining the answer to this question. We will do the tracing manually for illustration.

Look at your predicate:

once(X, [H | T]) :-
    \+ X = H,
    once(X, T).
once(X, [X | T]) :-
    \+ member(X, T).

Now consider the query:

once(X, [b,a,a,c,b,a]).

First, Prolog tries to execute the first sentence of your predicate. The head once(X, [H|T]), and the first expression \+ X = Hto become:

once(X, [b|[a,a,c,b,a]]) :-  % [H|T] instantiated with [b,a,a,c,b,a] here
                             %   So, H is b, and T is [a,a,c,b,a]
    \+ X = b,
    ...

X ( ) b , . , \+ X = b, X , , X = b X b .

, . . once(X, [X|T]) \+ member(X, T), :

once(b, [b|[a,a,c,b,a]]) :-    % X was instantiated with 'b' here,
                               %   and T instantiated with [a,a,c,b,a]
    \+ member(b, [a,a,c,b,a]).

member(b, [a,a,c,b,a]) , b [a,a,c,b,a]. , \+ member(b, [a,a,c,b,a]) .

.

once(X, [b,a,a,c,b,a]). . , . , \+ X = H ( X \= H, X , , , H. isn ' , .

:

once(X, L) :-           % X occurs once in L if...
    select(X, L, R),    % I can remove X from L giving R, and
    \+ member(X, R).    % X is not a member of R

select X, :

?- once(c, [b,a,a,c,b,a]).
true ;
false.

?-  once(b, [b,a,a,c,b,a]).
false.

?- once(X, [b,a,a,c,b,a]).
X = c ;
false.

, once, Prolog. .

+2

!

@lurker, :

onceMember_of(X,Xs) :-
   select(X,Xs,Xs0),
   maplist(dif(X),Xs0).

:

?- onceMember_of(c,[b,a,a,c,b,a]).
true ;                              % succeeds, but leaves choicepoint
false.
?- onceMember_of(b,[b,a,a,c,b,a]).
false.
?- onceMember_of(X,[b,a,a,c,b,a]).
X = c ;
false.

, !

?- onceMember_of(X,[A,B,C]).
X = A, dif(A,C), dif(A,B) ;
X = B, dif(B,C), dif(B,A) ;
X = C, dif(C,B), dif(C,A) ;
false.

:

?- length(Xs,_), onceMember_of(X,Xs).
Xs = [X] ;
Xs = [X,_A],        dif(X,_A) ;
Xs = [_A,X],        dif(X,_A) ;
Xs = [ X,_A,_B],    dif(X,_A), dif(X,_B) ;
Xs = [_A, X,_B],    dif(X,_A), dif(X,_B) ;
Xs = [_A,_B, X],    dif(X,_A), dif(X,_B) ;
Xs = [ X,_A,_B,_C], dif(X,_A), dif(X,_B), dif(X,_C) ...

, :

?- onceMember_of(X,Xs).
Xs = [X] ;
Xs = [X,_A],       dif(X,_A) ;
Xs = [X,_A,_B],    dif(X,_A), dif(X,_B) ;
Xs = [X,_A,_B,_C], dif(X,_A), dif(X,_B),dif(X,_C) ...

2015-05-13

, selectfirst/3, select/3:

onceMember_ofB(X,Xs) :-
   selectfirst(X,Xs,Xs0),
   maplist(dif(X),Xs0).

onceMember_of/2 onceMember_ofB/2 :

?- onceMember_of(c,[b,a,a,c,b,a]).
true ;                              % succeeds, but leaves choicepoint
false.
?- onceMember_ofB(c,[b,a,a,c,b,a]).
true.                               % succeeds deterministically

! :

?- onceMember_ofB(X,[A,B,C]).
X = A, dif(A,C), dif(A,B) ;
X = B, dif(B,C), dif(A,B),dif(B,A) ;             % 1 redundant constraint
X = C, dif(A,C),dif(C,A), dif(B,C),dif(C,B) ;    % 2 redundant constraints
false.

dif/2? maplist(dif(X),Xs0), :

onceMember_ofC(E,[X|Xs]) :-
   if_(E = X, maplist(dif(X),Xs),
              onceMember_ofC(E,Xs)).

, !

?- onceMember_ofC(X,[A,B,C]).
X = A, dif(A,C), dif(A,B) ;
X = B, dif(B,C), dif(B,A) ;
X = C, dif(C,B), dif(C,A) ;
false.
+2

Source: https://habr.com/ru/post/1534139/


All Articles