Prolog检查列表是否包含偶数个元素

时间:2018-06-07 20:00:23

标签: list recursion prolog tail head

我必须检查列表是否包含偶数个没有内置函数的元素。

示例:

containsEvenNumber([a,b,c,a,a], a).

返回false

containsEvenNumber([a,b,c,a], a).

返回true

现状:

not(A) :-
    A, !,
    fail.
not(_).
equal([E|_], E).
containsEvenNumber([], _).
containsEvenNumber([E|Tail], E) :-
    unevenCount(Tail, E).

containsEvenNumber([Head|Tail], E) :-
    not(equal([Head|Tail], E)),
    evenCount(Tail, E).

evenCount([], _).
evenCount([E|Tail], E) :-
    unevenCount(Tail, E).

evenCount([Head, Tail], E) :-
    not(equal([Head|Tail], E)),
    unevenCount(Tail, E).

unevenCount([], _) :-
    fail.
unevenCount([E, Tail], E) :-
    evenCount(Tail, E).

unevenCount([Head, Tail], E) :-
    not(equal([Head|Tail], E)),
    unevenCount(Tail, E).

我尝试在元素出现时在状态之间切换。 它不起作用,因为我从不进入状态,头部不是元素或者说是,我也进入状态,当头部是元素时返回false。

如何让它工作/修复它?

1 个答案:

答案 0 :(得分:4)

“状态之间切换”实际上是解决这个问题的好方法。逻辑应遵循以下简单规则:

  
      
  1. 如果X中有[X|Xs]个元素有奇数,则X中有Xs个元素。{/ p>

  2.   
  3. 如果X[Y|Xs]不同,则X中有Y个偶数元素,并且偶数X Xs中的元素。

  4.   
  5. 如果X中有{偶数[X|Xs]个元素,则X中的Xs元素数量奇数。

  6.   
  7. 如果X[Y|Xs]不同,则X中的Y个元素数量奇数,且X为奇数Xs中的元素。

  8.   

然后你有基本情况:

  

[]中有任意数量的元素。

     

X中有[X]个奇数。

您只需将这些规则写为Prolog即可。但是,您的实现存在一些问题。

在少数情况下,您要将列表编写为[Head, Tail]而不是[Head|Tail][Head, Tail]是两个元素的列表。另外,unevenCount/2的基本情况(我假设你的意思是奇数)是不正确的。如果您的基本案例始终失败,那么您的谓词将始终失败。除了少数例外,您应该编写谓词子句以成功,而不是失败。如果无法成功,将自动失败。

让我们试着写出上面的规则。 ISO Prolog已经\+,因此您无需定义not/1。另外,编写equal([E|_], E).是不必要的。您可以直接在代码中直接执行此操作。

evenCount(_, []).          % base case for even
evenCount(X, [X|Xs]) :-    % rule #1
    oddCount(X, Xs).
evenCount(X, [Y|Xs]) :-    % rule #2
    dif(X, Y),
    evenCount(X, Xs).

oddCount(X, [X]).          % base case for odd
oddCount(X, [X|Xs]) :-     % rule #3
    evenCount(X, Xs).
oddCount(X, [Y|Xs]) :-     % rule #4
    dif(X, Y),
    oddCount(X, Xs).

SWI Prolog定义dif/2。您也可以使用\==,但它不是dif/2的纯粹定义(因此不像通常那样)。