1

我正在尝试编写序言程序,将两个列表中的项目相加并将结果呈现在另一个列表中。

例如:

清单 1:

[1, 3, 4, 2]

清单 2:

[5, 1, 3, 0]

结果:

[6, 4, 7, 2]

到目前为止,我有这个:

list_sum([],[],[]).
list_sum([H1|T1],[H2|T2],L3):-list_sum(T1,T2,[X|L3]), X is H1+H2.

?-list_sum([1,2,3,4],[1,2,3,4],R),write(R).
4

6 回答 6

4

如果您使用 SWI-Prolog,您可以使用 maplist,并在那里找到模块 lambda: http: //www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl

:- use_module(library(lambda)).

list_sum(L1, L2, L3) :-
    maplist(\X^Y^Z^(Z is X + Y), L1, L2, L3).
于 2013-04-10T20:57:11.933 回答
2

@gusbro 说了什么。此外,您需要重新排列操作顺序并添加一些额外的特殊情况来处理不同长度的列表:

list_sum( []     , []     , []     ) .
list_sum( []     , [Y|Ys] , [Z|Zs] ) :- Z is 0+Y , list_sum( [] , Ys , Zs ) .
list_sum( [X|Xs] , []     , [Z|Zs] ) :- Z is X+0 , list_sum( Xs , [] , Zs ) .
list_sum( [X|Xs] , [Y|Ys] , [Z|Zs] ) :- Z is X+Y , list_sum( Xs , Ys , Zs ) .

您需要Z is X+Y在上面的示例中移动评估 ( ),以便在递归之前Z对其进行评估。这完成了两件事:

  • 首先,它使谓词tail-recursive,这意味着解决方案是迭代的,因此不会消耗堆栈空间。在您的代码中,直到整个递归完成后才会执行评估。每个中间和都保存在堆栈中,并在您备份的过程中从右到左进行评估。这意味着你会在一个大名单上炸掉你的筹码。

  • 其次,在递归之前评估每个结果意味着你很快就会失败。与结果不统一的第一个总和使整个操作失败。您的解决方案失败缓慢。考虑 10,000,000 个项目列表,其中第一个项目的总和不等于结果列表中的第一个项目:您将遍历所有 10,000,000 个项目,然后——假设你没有破坏你的堆栈——你开始从右到左计算总和。在最后一次评估之前,您的谓词不会失败​​。

于 2013-04-10T18:33:38.527 回答
2

它是 SWI-Prolog 中的一个衬垫:

list_sum(X,Y,S) :- maplist(plus, X,Y,S).

它也“向后”工作:

?- maplist(plus, [1,2,3],Y,[3,4,5]).
Y = [2, 2, 2].
于 2013-04-11T19:57:44.130 回答
1

你快到了。您的问题是 sum 的结果应该放在第二个子句的开头,而不是放在递归调用中!

list_sum([H1|T1],[H2|T2],[X|L3]):-list_sum(T1,T2,L3), X is H1+H2.

请注意,您编写它的方式,结果是“返回”的 L3 是一个列表,其中您已从Xrecusive 调用中删除了 head ( );而您的意思恰恰相反:将元素 ( X) 添加到结果列表中。

于 2013-04-10T18:09:13.760 回答
0

结果应该是一个列表,所以你不能只说X is H1+H2因为 X 不是一个列表,而你只是将列表的头部与单个变量匹配。出于同样list_sum([],[],0)的原因也不正确。答案如下所示:

sum([],[],[]).
sum([H1| T1], [H2| T2], [ResH| ResT]) :- 
        sum(T1, T2, ResT),
        ResH is H1+H2.

但是当你运行自己的代码时,第一次 X 与 H1+H2 匹配,在第二次递归调用时,X 有一个值,不能与 T1+T2 的头部匹配。所以它输出一个no.

于 2013-04-10T18:20:14.043 回答
0
domains
list=integer*
predicates
add(list,list,list)
clauses
add([],[],[]).
add([V1X|X],[V1Y|Y],[V1Z|Z]):-add(X,Y,Z),V1Z=V1X+V1Y.
于 2015-04-16T11:36:32.173 回答