如何为数字计数谓词实例化 Y?

时间:2021-05-12 06:13:33

标签: prolog

我有一个方法可以遍历一个数字 X,并计算它有多少个数字是偶数(这是 Y 参数的目的)

count_even(0,_). %base case
count_even(X,Y) :- mod(X,2)=:=0,%recursive case
    Y1 is Y + 1,
    X1 is X // 10, %if X is even
    count_even(X1,Y1)
    ;   mod(X,2)\==0, %if X is odd
    X1 is X // 10,
    count_even(X1,Y).

当然,通过调用 count_even(insert any number, 0) 并在基本情况下添加 write(y) 很容易获得结果,但是我需要确保当您为第二个参数输入变量时,该方法有效,例如 count_even(insert any number, A)

当然,这需要实例化 Y,但是在递归方法中放置一个简单的 Y is 0 将导致 Y 始终为 0 或 1,我不希望这样。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

您可以在基本情况下使用 Y 扭转计算并实例化 0。在偶数位的每一步中,它都会递增。

其他问题:在递归情况下,您必须确保X > 0,否则在回溯过程中您会得到其他错误答案。此外,算术不等于=\=\== 代替统一项,否定,这对于 mod(8,2)==0 也是如此)。这也会给您带来额外的错误结果。

固定代码:

count_even(0,0). %base case
count_even(X,Y) :- X > 0, X1 is X // 10, %recursive case
                  ((mod(X,2)=:=0, count_even(X1,Y1), Y is Y1 + 1); %if X is even
                   (mod(X,2)=\=0, count_even(X1,Y))). %if X is odd

答案 1 :(得分:0)

尝试这样的事情:

even_digits( N, Y ) :-  % the general case
    N > 0,              % - for N > 0,
    N1 is div(N,10) ,   % - get all digits to the left of the one's place
    D  is mod(N,10) ,   % - get the one's digit
    even_digits(N1,T) , % - recurse down on N1
    ( is_even(D)        % - if the one's digit is even
      -> Y is T+1       % - add 1 to the earlier result
      ;  Y is T         % - otherwise, we're done.
    ).                  % Easy!
even_digits( 0, 0 ).    % the base case. The question is... is zero even, odd, or signless. I've decided that it is signless here.

is_even(N) :- 0 =:= mod(N,2).

但这会让你处于一个零的奇怪地方。零是我们用完正数中的数字的点,但它本身也是一个数字。

您可能会发现将数字视为原子并将其分解为数字列表更容易。

even_digits( N, R ) :-
    number_chars(N,Ds),
    even_digits( Ds, 0 , R ).

even_digits( []     , N , N ).
even_digits( [D|Ds] , T , N ) :-
    ( member( D, ['0','2','4','6','8'] )
      -> T1 is T+1
      ;  T1 is T
    ),
    even_digits(Ds, T1, N).

这适用于负数、零、带小数值的数字。

相关问题