我需要编写一个程序,它使用以下条件从给定列表返回一个新列表。 如果列表成员为负数或0,则该值应为新列表的3倍。如果成员是肯定的,它应该为该列表增加2倍的值。 例如:
goal: dt([-3,2,0],R).
R = [-3,-3,-3,2,2,0,0,0].
我编写了以下代码,它对我来说很好,但它返回true
而不是R = [some_values]
我的代码:
dt([],R):- write(R). % end print new list
dt([X|Tail],R):- X =< 0, addNegavite(Tail,X,R). % add 3 negatives or 0
dt([X|Tail],R):- X > 0, addPositive(Tail,X,R). % add 2 positives
addNegavite(Tail,X,R):- append([X,X,X],R,Z), dt(Tail, Z).
addPositive(Tail,X,R):- append([X,X],R,Z), dt(Tail, Z).
也许有人知道如何打印R = []
而不是true
。
答案 0 :(得分:3)
为什么在你的条款中打电话给write
?
最好不要在你的条款中产生副作用:
dt([], []).
dt([N|NS], [N,N,N|MS]) :-
N =< 0,
dt(NS, MS).
dt([N|NS], [N,N|MS]) :-
N > 0,
dt(NS, MS).
这将有效:
?- dt([-3,2,0], R).
R = [-3, -3, -3, 2, 2, 0, 0, 0] .
在子句中不调用带副作用的函数的另一个好处是反过来也可以:
?- dt(R, [-3, -3, -3, 2, 2, 0, 0, 0]).
R = [-3, 2, 0] .
您可以在条款之外调用write
:
?- dt([-3,2,0], R), write(R).
[-3,-3,-3,2,2,0,0,0]
R = [-3, -3, -3, 2, 2, 0, 0, 0] .
答案 1 :(得分:3)
您的代码准备R
的值,因为它从顶部到底部递归到递归链,将传入的值视为初始列表。使用空列表调用dt/2
会产生所需的输出:
:- dt([-3,2,0],[]).
Demo #1 - 请注意相反的顺序
然而,这是在Prolog中执行操作的一种不寻常的方式:通常,R
是您的返回值,以相反的方式生成,当基本案例服务于“空列表”情况时,其余的规则从空列表中得出结果:
dt([],[]). % Base case: empty list produces an empty list
dt([X|Like],R):- X =< 0, addNegavite(Like,X,R).
dt([X|Like],R):- X > 0, addPositive(Like,X,R).
% The two remaining rules do the tail first, then append:
addNegavite(Like,X,R):- dt(Like, Z), append([X,X,X], Z, R).
addPositive(Like,X,R):- dt(Like, Z), append([X,X], Z, R).