1

我无法让以下工作。这是我到目前为止得到的:

stepen(2).
stepen(X):-
   X mod 2=:=0,
   X1 is X/2,
   stepen(X1).//stepen means power(in Serbian).

spoji([],Y,Y).
spoji([X|Xs],Y,[X|Z]):-spoji(Xs,Y,Z).//spoji means append lists

vadi(nil,[]).
vadi(t(X,L,R),[X|Xs]) :-
   stepen(X),
   vadi(L,SL),
   vadi(R,SR), 
   spoji(SL,SR,Xs).//list of nodes that are power of 2.
4

3 回答 3

1

(到目前为止,没有人评论您的代码。所以我会尝试)

stepen/1循环

我假设您在这里指的是两个的非负幂。即,2^(-1)不考虑等。

首先,您的定义会在符合 ISO 标准的系统(如stepen/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 2X1 is X >> 1.

这个程序现在会永远终止吗?毕竟X div 2会接近零。从消极的一面来看,它会结束-1,然后会失败。但从积极的方面来看,它将保持在0!

这是循环程序()减少到最低限度:

?- 斯蒂芬(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/3vl。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].
于 2014-06-30T19:11:01.673 回答
1

N您可能会发现这种确定2 的幂是否更有效的方法。这是一个利用整数值的二进制补码表示的小技巧:

is_power_of_two( N ) :-
  integer(N) ,
  N \= 0 ,
  0 is N /\ (N-1)
  .

编辑指出,无论整数的符号如何,该属性都为真:除了一个例外 - 0,因此测试非零 - 该属性为真的唯一二进制补码整数值是 2 的幂:

?- between(-1025,+1025,N),pow2(N).
N = 1 ;
N = 2 ;
N = 4 ;
N = 8 ;
N = 16 ;
N = 32 ;
N = 64 ;
N = 128 ;
N = 256 ;
N = 512 ;
N = 1024 ;
false.
于 2014-06-30T17:15:09.427 回答
0

如果您考虑到这一点1 is 2^0,则需要更改 stepen/1 谓词的基本情况。

需要更重要的更正,因为当在树中找到任何不是2 的幂的节点时,您的 vadi/2 谓词将失败。

然后你应该添加一个子句

vadi(t(X,L,R),Xs) :-
   % \+ stepen(X), this test is not mandatory, but it depends on *where* you add the clause
   vadi(L,SL), vadi(R,SR), spoji(SL,SR,Xs).
于 2014-06-28T15:45:48.883 回答