在Prolog中创建谓词,该谓词仅对列表中偶数的平方进行求和

时间:2016-04-07 07:24:44

标签: prolog clpfd

我试图找出如何在prolog中创建一个谓词,该谓词只对给定列表中偶数的平方进行求和。

预期产出:

?- sumsq_even([1,3,5,2,-4,6,8,-7], Sum).

Sum = 120 ;

false.

我所知道的是从列表中删除所有奇数:

sumsq_even([], []).
sumsq_even([Head | Tail], Sum) :-
    not(0 is Head mod 2),
    !,
    sumsq_even(Tail, Sum).
sumsq_even([Head | Tail], [Head | Sum]) :-  
    sumsq_even(Tail, Sum).

这给了我:

Sum = [2, -4, 6, 8]

而且我也知道如何将列表中所有数字的平方加起来:

sumsq_even([], 0)
sumsq_even([Head | Tail], Sum) :-
    sumsq_even(Tail, Tail_Sum),
    Sum is Head * Head + Tail_Sum.

但我似乎无法弄清楚如何将这两者连接在一起。我认为我可能对此采取了错误的方式,但我不确定如何定义适当的关系以使其有意义。

谢谢!

4 个答案:

答案 0 :(得分:2)

将您的问题分成更小的部分。正如您已经说过的,您有两种不同的功能应该结合起来:

  • 从列表中删除奇数(even
  • 汇总列表中数字的所有方块(sumsq

因此,首先,为不同的功能使用不同的谓词名称:

even([], []).
even([Head | Tail], Sum) :-
    not(0 is Head mod 2),
    !,
    even(Tail, Sum).
even([Head | Tail], [Head | Sum]) :-  
    even(Tail, Sum).

sumsq([], 0).
sumsq([Head | Tail], Sum) :-
    sumsq(Tail, Tail_Sum),
    Sum is Head * Head + Tail_Sum.

在第三个谓词中,您现在可以将两个后续较小的步骤组合在一起:

sumsq_even(List, Sum) :-
    even(List, Even_List),
    sumsq(Even_List, Sum).

在此规则中,首先将(输入)列表缩减为偶数元素(Even_List),然后计算平方和。

这是您的示例的结果:

sumsq_even([1,3,5,2,-4,6,8,-7], Sum).
S = 120.

答案 1 :(得分:2)

您可以实际执行这两项任务(过滤偶数并将它们相加):

vec3 entryPoint = vec3(0.0f);

if(scaleCoeff >= 2.7f)
{
    float tmp = min((scaleCoeff - 2.7f) * 0.1f, 1.0f);
    entryPoint = EntryPoint + tmp * (exitPoint - EntryPoint);
}
else
{
    entryPoint = EntryPoint;
}
//

查询谓词会得到所需的结果:

:- use_module(library(clpfd)).

nums_evensumsq([],0).
nums_evensumsq([X|Xs],S0) :-
    X mod 2 #= 0,
    nums_evensumsq(Xs,S1),
    S0 #= S1 + X * X.
nums_evensumsq([X|Xs],S) :-
    X mod 2 #= 1,
    nums_evensumsq(Xs,S).

您可以使用if_ / 3定义here

来编写更短的内容
   ?- nums_evensumsq([1,3,5,2,-4,6,8,-7],S).
S = 120 ? ;
no

请注意,if_ / 3的第一个参数中的比较是使用= / 3定义的here

答案 2 :(得分:2)

使用和Prolog 写:

:- use_module(library(clpfd)).
:- use_module(library(lambda)).

zs_sumevensq(Zs, S) :-
   maplist(\Z^X^(X #= Z*Z*(1-(Z mod 2))), Zs, Es),
   sum(Es, #=, S).

OP给出的示例查询:

?- zs_sumevensq([1,3,5,2,-4,6,8,-7], S).
S = 120.

答案 3 :(得分:0)

掌握了基础知识后,您可能有兴趣了解内置函数。库aggregate提供了一种处理列表的简单方法,使用member / 2作为列表元素' accessor':

sumsq_even(Ints, Sum) :-
  aggregate(sum(C), I^(member(I, Ints), (I mod 2 =:= 0 -> C is I*I ; C = 0)), Sum).