Check if all the numbers in the list are different in the prolog

I want to create a rule in the prolog that checks if there is a duplicate number in the list.

For instance:

  • for [1,2,3,4] it will return true .
  • for [1,2,3,3] it will return false because 3 repeated

I came up with this rule, but it does not work

 Different([]). Different([H|T]):- Member(H,T), Different(T). 

Any ideas?

+6
source share
7 answers

compact definition can be

 all_diff(L) :- \+ (select(X,L,R), memberchk(X,R)). 

i.e. all elements are different, if we can’t glance at one and find it otherwise ...

change

Let (slightly) improve efficiency: it is useless to check if X is a member of the sublist prefix, therefore:

 all_diff(L) :- \+ (append(_,[X|R],L), memberchk(X,R)). 
+9
source

The easiest way to verify that all members of a list are unique is to sort the list and verify that the length of the sorted list is equal to the length of the original list.

 different(X) :- sort(X, Sorted), length(X, OriginalLength), length(Sorted, SortedLength), OriginalLength == SortedLength. 

Your solution does not work due to incorrect syntax (facts and predicates should not start with a capital letter) and a logical error. A list is unique if head H not a member of the tail T list and tail T is unique:

 different([]). different([H|T]):- \+member(H,T), different(T). 
+4
source

If all the numbers in this list are integers, and if your Prolog implementation offers , you do not need to write new predicates - just use the predefined predicate all_different/1 !

 :- use_module(library(clpfd)). 

Using an example:

  ? - all_different ([1,2,3,4]).
 true

 ? - all_different ([1,2, 3 , 3 ]).
 false
+4
source

A very simple answer ...

Code:

unique([]). unique([_,[]]). unique([H|T]):-not(member(H,T)),unique(T).

Tests:

?-unique([1,2,3,4]). true. ?-unique([1,2,3,3]). false. ?-unique([a,b,12,d]). true ?-unique([a,b,a]). false

+1
source

The clear way I came up with is this:

If all members of the list are different from each other, then if I ask the prolog to select all the pairs (I,J) , so that I,J are members of the list, and also I is equal to J , then for each element in the list he can find one such A couple that is an element with itself.

Therefore, if we can put all such pairs in a list, then the length of this list should have the same length as the original list.

Here is my prolog code:

 all_diff(L) :- findall((I,J), (member(I, L), member(J, L), I == J), List), length(L, SupposedLength), length(List, CheckThis), SupposedLength == CheckThis. 
0
source

The rule presented in the question is very close to the correct answer with minimal use of the library. Here's the working version, requiring only one change, adding \ + in the third line:

 uniqueList([]). uniqueList([H|T]):- \+(member(H,T)), uniqueList(T). 

Explanation of the code for beginners Prolog: the element predicate (H, L) checks whether element H is a member of the list L. \ + is the negation function of Prolog, therefore the above code values ​​in:

 uniqueList([H|T]) returns true if: (H doesn't have a copy in T) and uniqueList(T) 

While the code of the original crawler did not work, because it was:

 uniqueList([H|T]) returns true if: (H has a copy in T) and uniqueList(T) 

* I renamed Different () to uniqueList () because it reads better. The convention is to reserve capital letters for variables.

-1
source

This is not very effective, but for each number you can check whether it appears later. For instance:

 Different([H|T]):- CheckSingle(H, [T]), Different([T]). Checksingle(_,[]). Checksingle(Elem, [H, T]):- Elem != H, Checksingle(Elem, [T]). 
-3
source

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


All Articles