'I would like to check in prolog if one list has the same elements
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?
Solution 1:[1]
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] ? ;
...
Solution 2:[2]
same(L) :-
maplist(=(_),L).
| ?- maplist(=(_),L).
L = []
L = [_]
L = [A,A]
L = [A,A,A]
L = [A,A,A,A]
L = [A,A,A,A,A]
See also this answer.
Solution 3:[3]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Community |
| Solution 3 |
