Prolog -只有偶数的过滤器列表



我有一个next Prolog函数,它只将您输入的任何数字(F)与列表中的每个元素[]相乘,例如输入:multiplyf(2, [5,4,8], N).输出:[10,8,16]。这个函数可以正常工作(你可以尝试一下),但现在我只需要过滤偶数乘以F保持奇数相同,之前的例子:输入:multiplyf(2, [5,4,8], N)。输出:[5,8,16],任何想法我可以过滤这个列表?我试了很多方法,但还是没有得到答案。

multiplyf(_,[],[]):-!.
multiplyf(F,[X|Xs], [Y|Ys]):-
Y is F*X,
multiplyf(F, Xs, Ys), !.

我试着:

even(X) :- 
Y is mod(X,2),
Y =:= 0.

但是当我在第一个函数中插入偶数(X)时,它也不起作用。

谢谢。

当我们在编写高尔夫代码时,下面这个怎么样:

multiplyf(_F, [], []).
multiplyf(F, [X | Xs], [Y | Ys]) :-
Y is X + ((1 - (X mod 2)) * X * (F - 1)),
multiplyf(F, Xs, Ys).

根据X mod 2是0还是1,Y计算为X + X * (F - 1),即X * F,或计算为X + 0 * Something,即x。

给你:

?- multiplyf(3, [1, 2, 3, 4, 5], Ys).
Ys = [1, 6, 3, 12, 5] ;
false.

这在我的旧版本的wi - prolog上留下了一个选择点。新版本是否更愿意索引非第一个参数?

另一个答案在精神上是可以的,但在细节上却是一团糟。也许@Nicholas Carey只是想激怒我;-)

可以在整数的最低有效位上使用位掩码来测试奇数和偶数。

odd(X) :- X / 0x1 =:= 1.
even(X) :- X / 0x1 =:= 0.

还有其他方法可以实现相同的功能,但这是输入最少的方法。阅读is/2上的文档,了解编写0 is something something的缺陷。

如果你想完全避免切割,你可以使用下面的易于理解和文档化的方法,利用子句对第一个参数的索引。

mf(Factor, Xs, Ys) :-
mf_1(Xs, Factor, Ys).
mf_1([], _, []).
mf_1([X|Xs], F, Ys) :-
LSB is X / 0x1,
mf_2(LSB, X, Xs, F, Ys).
mf_2(0 /* even */, X, Xs, F, [Y|Ys]) :-
Y is 2 * X,
mf_1(Xs, F, Ys).
mf_2(1 /* odd */, X, Xs, F, [X|Ys]) :-
mf_1(Xs, F, Ys).

这没有剪切或->,没有选择点,也不能使用浮点数。

修改multiply/3:

multiplyf( _ , []    , []     ) :- ! .
multiplyf( F ,[X|Xs] , [Y|Ys] ) :-
Y is F * X,
multiplyf(F,Xs,Ys), !.

很简单:

multiply_evens( _ , []     , []     ) .
multiply_evens( X , [Y|Ys] , [Z|Zs] ) :- even(Y), Z is X * Y , multiply(X,Ys,Zs) .
multiply_evens( X , [Y|Ys] , [Y|Zs] ) :- odd(Y), multiply_evens(X,Ys,Zs) .
even(X) :- 0 is X mod 2 .
odd(X)  :- 1 is X mod 2 .

这也是最具声明性的解决方案。对其意图几乎没有什么可怀疑的。

你可以使用cut (!)来减少一个选择点(毕竟,所讨论的数字不会停止为正/负):

multiply_evens( _ , []     , []     ) .
multiply_evens( X , [Y|Ys] , [Z|Zs] ) :- even(Y), !, Z is X * Y , multiply(X,Ys,Zs) .
multiply_evens( X , [Y|Ys] , [Y|Zs] ) :- multiply_evens(X,Ys,Zs) .
even(X) :- 0 is X mod 2 .

你可以使用软剪切:

来进一步压缩它
multiply_evens( _ , []     , []     ) .
multiply_evens( X , [Y|Ys] , [Z|Zs] ) :-
( even(Y) -> Z is X * Y ; Z is X ),
multiply(X,Ys,Zs) .
even(X) :- 0 is X mod 2 .

从列表遍历中提取乘法位需要注意:

multiply_evens( _ , []     , []     ) .
multiply_evens( X , [Y|Ys] , [Z|Zs] ) :- multiply_even(X,Y,Z), multiply_evens(X,Ys,Zs) .
multiple_even(X,Y,Z) :- even(Y), !, Z is X * Y .
multiply_even(_,Y,Y) .
even(X) :- 0 is X mod 2 .

相关内容

  • 没有找到相关文章

最新更新