序言中的尾递归程序,计算正数和负数
Tail-recursive program in prolog which counts positive and negative numbers
我想在 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.
问题是,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/5
(我检查是否 < 0
,而在前一种情况下您检查 > 0
)。
我想在 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.
问题是,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/5
(我检查是否 < 0
,而在前一种情况下您检查 > 0
)。