(到目前为止,没有人评论您的代码。所以我会尝试)
stepen/1
循环
我假设您在这里指的是两个的非负幂。即,2^(-1)
不考虑等。
首先,您的定义会在符合 ISO 标准的系统(如gnu-prolog或sicstus-prologstepen/1
)中产生错误。
| ?- stepen(6).
! Type error in argument 2 of (is)/2
! expected an integer, but found 3.0
! goal: _193 is 3.0 mod 2
这是因为X1 is X/2
它总是产生浮点数或错误,但绝不会产生整数。您可以将其替换X1 is X div 2
为X1 is X >> 1
.
这个程序现在会永远终止吗?毕竟X div 2
会接近零。从消极的一面来看,它会结束-1
,然后会失败。但从积极的方面来看,它将保持在0
!
这是循环程序(failure-slice)减少到最低限度:
?- 斯蒂芬(0)。
stepen(2) :-错误。
斯蒂芬(X):-
X 模 2=:=0,
X1 是 X 格 2,
步进(X1),假。% stepen 表示权力(在塞尔维亚语中)。
正如 Nicholas Carey 所建议的,您可以将此谓词简化为:
stepen(X) :-
X > 0,
X /\ (X-1) =:= 0.
vadi/2
逻辑
在您的定义中,如果树的所有节点都是 2 的幂,则此谓词为真。我假设您想“过滤掉”这些权力。最简单的方法是使用 DCGs 而不是spojii/3
vl。append/3
. 让我们首先考虑一个更简单的情况,只是树的节点:
nodes(nil) --> [].
nodes(t(X, L, R)) -->
[X],
nodes(L),
nodes(R).
| ?- T = t(1,nil,t(2,t(3,nil,t(4,nil,nil)),t(5,nil,nil))), phrase(nodes(T),L).
T = t(1,nil,t(2,t(3,nil,t(4,nil,nil)),t(5,nil,nil))),
L = [1,2,3,4,5].
现在,您不再需要所有元素,但只有确定,我将为此使用单独的非终结符:
st(E) --> {stepen(E)}, [E].
st(E) --> {\+stepen(E)}. % nothing!
或者更简洁:
st(E) --> {stepen(E)} -> [E] ; [].
现在,最终的非终端是:
stepeni(nil) --> [].
stepeni(t(X,L,R)) -->
st(X),
stepeni(L),
stepeni(R).
?- T = t(1,nil,t(2,t(3,nil,t(4,nil,nil)),t(5,nil,nil))), phrase(stepeni(T),L).
T = t(1,nil,t(2,t(3,nil,t(4,nil,nil)),t(5,nil,nil))),
L = [1,2,4].