I need to find the first duplicate value in a list.
prep(3,[1,3,5,3,5]). Should be true.
prep(5,[1,3,5,3,5]). Should be false.
I thought checking for equality with the current value and the previous list members until I find a duplicate, if it finds one it will test for equality with X but I have no idea how to do that in Prolog!
I appreciate any help! Thanks
Here is a pure version using dif/2 which implements sound inequality. dif/2 is offered by B-Prolog, YAP-Prolog, SICStus-Prolog and SWI-Prolog.
firstdup(E, [E|L]) :-
member(E, L).
firstdup(E, [N|L]) :-
non_member(N, L),
firstdup(E, L).
member(E, [E|_L]).
member(E, [_X|L]) :-
member(E, L).
non_member(_E, []).
non_member(E, [F|Fs]) :-
dif(E, F),
non_member(E, Fs).
The advantages are that it can also be used with more general queries:
?- firstdup(E, [A,B,C]). E = A, A = B ; E = A, A = C ; E = C, B = C, dif(A, C) ; false.
Here, we get three answers: A is the duplicate in the first two answers, but on two different grounds: A might be equal to B or C. In the third answer, B is the duplicate, but it will only be a duplicate if C is different to A.
To understand the definition, read :- as an arrow ← So what is on the right-hand side is what you know and on the left is what you conclude. It is often in the beginning a bit irritating to read predicates in that direction, after all you might be tempted to follow "the thread of execution". But often this thread leads to nowhere – it gets too complex to understand.
The first rule reads:
ProvidedEis an element of listLwe conclude that[E|L]hasEas first duplicate.
The second rule reads:
ProvidedEis the first duplicate ofL(don't panic here and say we don't know that ...) and provided thatNis not an element ofLwe conclude that[N|L]hasEas first duplicate.
The member/2 predicate is provided in many Prolog systems and non_member(X,L) can be defined as maplist(dif(X),L). Thus one would define firstdup/2 rather as:
firstdup(E, [E|L]) :-
member(E, L).
firstdup(E, [N|L]) :-
maplist(dif(N), L),
firstdup(E, L).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With