oralo
oralo

Reputation: 17

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?

Upvotes: 1

Views: 6796

Answers (4)

false
false

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

lurker
lurker

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

DiCaprio
DiCaprio

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

magus
magus

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

Related Questions