我必须检查列表是否包含偶数个没有内置函数的元素。
示例:
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。
如何让它工作/修复它?
答案 0 :(得分:4)
“状态之间切换”实际上是解决这个问题的好方法。逻辑应遵循以下简单规则:
如果
X
中有[X|Xs]
个元素有奇数,则X
中有Xs
个元素。{/ p>如果
X
和[Y|Xs]
不同,则X
中有Y
个偶数元素,并且偶数X
Xs
中的元素。如果
X
中有{偶数[X|Xs]
个元素,则X
中的Xs
元素数量奇数。- 醇>
如果
X
和[Y|Xs]
不同,则X
中的Y
个元素数量奇数,且X
为奇数Xs
中的元素。
然后你有基本情况:
[]
中有任意数量的元素。
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
的纯粹定义(因此不像通常那样)。