prolog中计算正数和负数的尾部递归程序

prolog中计算正数和负数的尾部递归程序,prolog,tail-recursion,Prolog,Tail Recursion,我想在prolog中编写一个尾部递归程序:count_neg(Ls,N,R)如果Ls是一个整数列表,而N是负元素的数量,则这是真的R应表示非负元素列表 例如: count_neg([1,-2,0,1,2,-3],N,R). N = 2, R = 4. 以下是我迄今为止编写的代码: count_neg(Ls, N, R) :- count_neg(Ls, 0, 0, N, R). count_neg([L|Ls], Cnt1, Cnt2, N, R) :- (L > 0 -> C1

我想在prolog中编写一个尾部递归程序:
count_neg(Ls,N,R)
如果
Ls
是一个整数列表,而
N
是负元素的数量,则这是真的<代码>R应表示非负元素列表

例如:

count_neg([1,-2,0,1,2,-3],N,R).
N = 2,
R = 4.
以下是我迄今为止编写的代码:

count_neg(Ls, N, R) :- count_neg(Ls, 0, 0, N, R).
count_neg([L|Ls], Cnt1, Cnt2, N, R) :- (L > 0 -> C1 is Cnt1 + 1, !; L < 0 -> C2 is Cnt2 + 1, !), count_neg(Ls, C1, C2, N, R).

count_neg([], Cnt1, Cnt2, N, R) :- N is Cnt1.
count_neg([], Cnt1, Cnt2, N, R) :- R is Cnt2.
count_neg(Ls,N,R):-count_neg(Ls,0,0,N,R)。
计数负([L | Ls],Cnt1,Cnt2,N,R):-(L>0->C1是Cnt1+1,!;L<0->C2是Cnt2+1,!),计数负(Ls,C1,C2,N,R)。
计数负([],Cnt1,Cnt2,N,R):-N是Cnt1。
计数负([],Cnt1,Cnt2,N,R):-R是Cnt2。
问题是,
N
R
在开始时都用0初始化,这是正确的,但是当程序应该计数第一个负数时,它不会从零开始计数,而是从_21532开始计数,结果是错误的:


有人知道这里出了什么问题吗?我还想在我的程序中使用Cuts。

问题在于您没有正确更新索引,并且调用谓词
is/2
,参数没有实例化。 一个可能的解决办法是:

count_neg(Ls, N, R):- 
    count_neg(Ls, 0, 0, N, R).

count_neg([],C1,C2,C1,C2).
count_neg([L|Ls], Cnt1, Cnt2, N, R):- 
    (L > 0 -> 
        C1 is Cnt1 + 1,
        C2 is Cnt2
    ;
        C2 is Cnt2 + 1,
        C1 is Cnt1), 
    count_neg(Ls, C1, C2, N, R).

?- count_neg([1,-2,0,1,2,-3,8],N,R).
N = 4
R = 3
另外,您不需要最后两个谓词和剪切。在问题中,你说
R
应该表示一个列表,但在前面的解决方案中,你没有得到列表。要获得它,您可以如下修改程序:

countNeg(L,N,R):-
    countNeg(L,N,0,R,[]).

countNeg([],N,N,R,R).
countNeg([H|T],N,C,R,L1):-
    (   H < 0 ->  
        C1 is C+1,
        countNeg(T,N,C1,R,L1);
    append(L1,[H],L2),
    countNeg(T,N,C,R,L2)).

?- countNeg([1,-2,0,1,2,-3],N,R).
N = 2
R = [1, 0, 1, 2]
countNeg(L,N,R):-
countNeg(L,N,0,R,[])。
countNeg([],N,N,R,R)。
countNeg([H | T],N,C,R,L1):-
(H<0->
C1是C+1,
countNeg(T,N,C1,R,L1);
附加(L1[H],L2),
countNeg(T,N,C,R,L2))。
?-countNeg([1,-2,0,1,2,-3],N,R)。
N=2
R=[1,0,1,2]

在这个解决方案中,您还可以注意到,您在每个分支中调用了
countNeg/5
(我检查
<0
,而在前面的例子中,您检查
>0
)。

为什么所有的剪切?