检查列表中列表中的所有数字是否不同

时间:2013-11-21 21:08:30

标签: prolog

我想在prolog中创建一个规则来检查列表中是否有重复的数字。

例如:

  • 对于[1,2,3,4],它将返回true
  • 对于[1,2,3,3],它将返回false,因为重复了3

我想出了这个规则,但它没有工作

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

有什么想法吗?

7 个答案:

答案 0 :(得分:10)

紧凑的定义可能是

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

即。如果我们不能偷看并在其余部分找到它,所有元素都是不同的......

修改

让(稍微)提高效率:检查X是否是前缀子列表的成员是没用的,所以:

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

答案 1 :(得分:4)

检查所有列表成员是唯一的最简单方法是对列表进行排序,并检查已排序列表的长度是否等于原始列表的长度。

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

由于语法错误(事实和谓词不应以大写字母开头)和逻辑错误,您的解决方案无效。如果标题H 是列表尾部T的成员且尾部T是唯一的,则列表是唯一的:

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

答案 2 :(得分:4)

如果该列表中的所有数字都是整数,并且Prolog实现提供了,那么就不需要编写自己的新谓词 - 只需使用预定义的谓词{{3} }!

:- use_module(library(clpfd)).

样品使用:

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

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

答案 3 :(得分:1)

非常简单的答案......

代码:

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

试验:

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

答案 4 :(得分:0)

我想出的一个简洁的方法如下:

如果列表中的所有成员彼此不同,那么如果我告诉prolog选择所有对(I,J),使I,J成为列表的成员,并且I是相等的到J,然后对于列表中的每个元素,它只能找到一个这样的对,它就是自身的元素。

因此,如果我们可以将所有这些对放在一个列表中,那么这个列表的长度应该与原始列表的长度相同。

这是我的序言代码:

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

答案 5 :(得分:-1)

问题中提供的规则非常接近正确答案,并且库使用最少。这是一个只需要进行一次更改的工作版本,在第三行中添加了 \ +

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

Prolog初学者代码的说明:成员(H,L)谓词检查元素H是否是列表L的成员。 \ + 是Prolog的否定函数,因此上面的代码量到:

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

原始提问者的代码不起作用,因为它等于:

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

*我将Different()重命名为uniqueList(),因为它读得更好。惯例是为变量保留大写字母。

答案 6 :(得分:-3)

这不是很有效,但是对于每个号码,您可以检查它是否稍后再次出现。像这样:

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

Checksingle(_,[]).

Checksingle(Elem, [H, T]):-
  Elem != H,
  Checksingle(Elem, [T]).