Reputation: 17
I would like to write in prolog "check if one list has the same elements" e.g list[a,a,a,a] is true. list[a,c,a,a] is false. How can I do so?
Upvotes: 1
Views: 6796
Reputation: 10102
same(L) :-
maplist(=(_),L).
?- maplist(=(_),L).
L = []
; L = [_A]
; L = [_A,_A]
; L = [_A,_A,_A]
; L = [_A,_A,_A,_A]
; L = [_A,_A,_A,_A,_A]
; L = [_A,_A,_A,_A,_A,_A]
; ... .
See also this answer.
Upvotes: 3
Reputation: 58244
It can be done with one, simple predicate:
same([]). % You only need this one if you want the empty list to succeed
same([_]).
same([X,X|T]) :- same([X|T]).
Results:
| ?- same([a,b,a,a]).
no
| ?- same([a,a,a,a]).
true ? ;
no
| ?- same([]).
yes
ADDENDUM 1
Changing the order of the clauses so that the base cases are first allows:
| ?- same(L).
L = [] ? ;
L = [_] ? ;
L = [A,A] ? ;
L = [A,A,A] ? ;
...
ADDENDUM 2
Another approach, using DCG, might be:
same(_) --> [].
same(X) --> [X], same(X).
Then:
| ?- phrase(same(_), [a,b,a,a]).
no
| ?- phrase(same(_), [a,a,a,a]).
true ? a
(1 ms) no
| ?- phrase(same(X), L).
L = [] ? ;
L = [X] ? ;
L = [X,X] ? ;
L = [X,X,X] ? ;
...
Upvotes: 5
Reputation: 833
Okay, now that I understood the request whats about this:
compare([X|Y]):-help(Y,X).
compare([]).
help([],_).
help([Y|X],Y) :- help(X,Y).
Upvotes: 2
Reputation: 1357
Using the built-in list_to_set/2, this can be done in a single line:
?- list_to_set([a,a,a,a],[_]).
true.
?- list_to_set([a,a,c,a],[_]).
false.
The conversion of a list to a set removes duplicates.. so if you are left with a list that can be unified to one item [_], then there are no duplicates.
If the list has duplicates, there will be > 1 item in the set, and the [_] predicate unification will fail.
This obviously won't work on an empty list - a separate rule will be needed for that.
Upvotes: 1