Prolog 规则,用 0 替换列表中的每个负数
Prolog rule which replaces with 0 every negative number from a list
我需要编写一个规则,用 0 替换列表中的每个负数。这是我的代码:
neg_to_0(L,R) :-
(
nth1(X,L,E),
E<0,
replace(E,0,L,L2),
neg_to_0(L2,R2)
) ;
R = L.
replace(_, _, [], []).
replace(O, R, [O|T], [R|T2]) :- replace(O, R, T, T2).
replace(O, R, [H|T], [H|T2]) :- H \= O, replace(O, R, T, T2).
我有一个规则“replace”,它将需要替换为 0 的元素和 returns 新列表,但它在规则替换值和 return 之后停止新列表,所以我制作了用新数据调用主函数的函数,以便它可以替换其他负值:
replace(E,0,L,L2),
neg_to_0(L2,R2)
);
R = L.
在最后一次迭代中,当它无法检测到任何负数时,我这样做是为了保存最后一个正确的列表,但我只得到一个“True”而不是正确的列表。
您的代码似乎...非常复杂。
您似乎在尝试编写过程性(命令式)代码。 Prolog 不是命令式语言:它描述“真相”并让 Prolog 的“推理引擎”找出真相。而且,在 Prolog 中,几乎所有的东西本质上都是递归的。
所以,对于你的问题,我们只有几个简单的案例:
空列表[]
,在这种情况下,转换后的列表是...空列表。
非空列表。 [N|Ns]
将其分解为头部 (N
) 和尾部 (Ns
)。如果 N < 0,我们将其替换为 0;否则我们保持原样。然后我们在尾部向下递归。
要用零替换列表中的负数,您只需要这样做:
%
% negatives_to_zero/2 replaces negative numbers with 0
%
negatives_to_zero( [] , [] ) . % nothing to do for the empty list
negatives_to_zero( [N|Ns] , [M|Ms] ) :- % for a non-empty list,
M is max(N,0), % get the max of N and 0,
negatives_to_zero(Ns,Ms). % and recurse down on the tail
您可以很容易地概括这一点,当然可以钳制 数字或数字列表,并将它们限制在指定范围内:
%--------------------------------------------------------------------------------
% clamp( N , Min, Max, R )
%
% Constrain N such that Min <= N <= Max, returning R
%
% Use -inf (negative infinity) to indicate an open lower limit
% Use +inf (infinity) or +inf (positive infinity) to indicate an open upper limit
% -------------------------------------------------------------------------------
clamp( Ns , -inf , +inf , Ns ) .
clamp( N , Min , Max , R ) :- number(N) , clamp_n(N,Min,Max,R).
clamp( Ns , Min , Max , Rs ) :- listish(Ns) , clamp_l(Ns,Min,Max,Rs).
clamp_n( N , _ , _ , R ) :- \+number(N), !, R = N.
clamp_n( N , Min , Max , R ) :- T is max(N,Min), R is min(T,Max).
clamp_l( [] , _ , _ , [] ) .
clamp_l( [X|Xs] , Min , Max , [Y|Ys] ) :- clamp_n(X,Min,Max,Y), clamp(Xs,Min,Max,Ys).
listish( T ) :- var(T), !, fail.
listish( [] ) .
listish( [_|_] ) .
我需要编写一个规则,用 0 替换列表中的每个负数。这是我的代码:
neg_to_0(L,R) :-
(
nth1(X,L,E),
E<0,
replace(E,0,L,L2),
neg_to_0(L2,R2)
) ;
R = L.
replace(_, _, [], []).
replace(O, R, [O|T], [R|T2]) :- replace(O, R, T, T2).
replace(O, R, [H|T], [H|T2]) :- H \= O, replace(O, R, T, T2).
我有一个规则“replace”,它将需要替换为 0 的元素和 returns 新列表,但它在规则替换值和 return 之后停止新列表,所以我制作了用新数据调用主函数的函数,以便它可以替换其他负值:
replace(E,0,L,L2),
neg_to_0(L2,R2)
);
R = L.
在最后一次迭代中,当它无法检测到任何负数时,我这样做是为了保存最后一个正确的列表,但我只得到一个“True”而不是正确的列表。
您的代码似乎...非常复杂。
您似乎在尝试编写过程性(命令式)代码。 Prolog 不是命令式语言:它描述“真相”并让 Prolog 的“推理引擎”找出真相。而且,在 Prolog 中,几乎所有的东西本质上都是递归的。
所以,对于你的问题,我们只有几个简单的案例:
空列表
[]
,在这种情况下,转换后的列表是...空列表。非空列表。
[N|Ns]
将其分解为头部 (N
) 和尾部 (Ns
)。如果 N < 0,我们将其替换为 0;否则我们保持原样。然后我们在尾部向下递归。
要用零替换列表中的负数,您只需要这样做:
%
% negatives_to_zero/2 replaces negative numbers with 0
%
negatives_to_zero( [] , [] ) . % nothing to do for the empty list
negatives_to_zero( [N|Ns] , [M|Ms] ) :- % for a non-empty list,
M is max(N,0), % get the max of N and 0,
negatives_to_zero(Ns,Ms). % and recurse down on the tail
您可以很容易地概括这一点,当然可以钳制 数字或数字列表,并将它们限制在指定范围内:
%--------------------------------------------------------------------------------
% clamp( N , Min, Max, R )
%
% Constrain N such that Min <= N <= Max, returning R
%
% Use -inf (negative infinity) to indicate an open lower limit
% Use +inf (infinity) or +inf (positive infinity) to indicate an open upper limit
% -------------------------------------------------------------------------------
clamp( Ns , -inf , +inf , Ns ) .
clamp( N , Min , Max , R ) :- number(N) , clamp_n(N,Min,Max,R).
clamp( Ns , Min , Max , Rs ) :- listish(Ns) , clamp_l(Ns,Min,Max,Rs).
clamp_n( N , _ , _ , R ) :- \+number(N), !, R = N.
clamp_n( N , Min , Max , R ) :- T is max(N,Min), R is min(T,Max).
clamp_l( [] , _ , _ , [] ) .
clamp_l( [X|Xs] , Min , Max , [Y|Ys] ) :- clamp_n(X,Min,Max,Y), clamp(Xs,Min,Max,Ys).
listish( T ) :- var(T), !, fail.
listish( [] ) .
listish( [_|_] ) .