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).

我有一个规则“re​​place”,它将需要替换为 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( [_|_] ) .