prolog谓词检查元素是否在列表中至少出现两次

时间:2017-03-30 16:24:15

标签: list prolog

twice(X,[X|Y]):-
   member(X,[Y]).
twice(X,[Y|Z]):-
   twice(X,[Z]),
   X\=Y.

我找不到任何语法错误,但每次都执行失败。

3 个答案:

答案 0 :(得分:3)

您对列表结构存在误解。列表[H|T]包含元素 H和尾部列表 T。所以T本身就是一个列表。如果您放置[T],那么该列表只包含一个元素,该元素就是列表T

此外,在您的第二个谓词条款中,您不需要X参数或检查X \= Y,因为如果您正在检查它并不是真的相关至少两次。

因此,您的解决方案稍有改变:

twice(X, [X|T]) :-
    member(X, T).
twice(X, [_|T]) :-
    twice(X, T).

如果X[X|T] X的成员,那么 TX中出现两次如果[_|T]X 中出现两次T,则localStorage.removeItem('favorties'); 会发生两次。

答案 1 :(得分:3)

我喜欢你的意图,但不能重现你所说的:这个谓词一直都在失败。事实上,它循环!以下是

的片段
twice(X,[X|Y]):- false,
   member(X,[Y]).
twice(X,[Y|Z]):-
   twice(X,[Z]), false,
   X\=Y

?- twice(a,[a,a]).

因为这个片段循环,你的原始程序也循环。 Lurker已经告诉你什么是错的。以下是一些替代配方:

twice(X, Xs) :-
   phrase( ( ..., [X], ..., [X], ... ), Xs).

... --> [] | [_], ... .

然而,这个程序有一个很大的缺陷:

?- twice(a,[a,a,a]).
   true
;  true
;  true
;  false.

我们的答案完全相同。有一次绰绰有余!

模糊性来自... - 非终端,这意味着任何序列。有三种方式与列表[a,a,a]匹配:

     [     a,      a,      a     ]

      ...,[X],...,[X],    ...
      ...,[X],    ...,    [X],...
          ...,    [X],...,[X],...

要消除歧义,我们需要用更具体的内容替换...。除了X之外,序列应该匹配任何内容。这样只剩下第一场比赛。

twice(X, Xs) :-
       phrase( ( all(dif(X)), [X], all(dif(X)), [X], ... ), Xs).

all(_) --> [].
all(P_1) -->
   [E],
   {call(P_1,E)},
   all(P_1).

?- twice(a,[a,a,a]).
   true
;  false.

那要好得多。但这是最好的吗?对SICStus | SWI使用library(reif)进行了进一步改进。

:- use_module(library(reif)).

twice(C, [X|Xs]) :-
   if_(C = X, memberd(X, Xs), twice(C, Xs) ).

memberd(C, [X|Xs]) :-
   if_(C = X, true, memberd(C, Xs) ).

?- twice(a,[a,a,a]).
   true.

答案 2 :(得分:0)

twicee(X,[X|Y]):- member(X,Y).
twicee(X,[_|Y]):-twicee(X,Y), X\=Y.

为我工作的代码,请检查列表中是否有两个元素。例如:

twicee(X,[a,a,b,b,c,d]).
X = a.
X= b.

twicee(c,[a,a,b,b,d]).
FALSE.