Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List Prolog-对两个列表中的数字求和_List_Lambda_Prolog_Add - Fatal编程技术网

List Prolog-对两个列表中的数字求和

List Prolog-对两个列表中的数字求和,list,lambda,prolog,add,List,Lambda,Prolog,Add,我正试图编写一个prolog程序,对两个列表中的项求和,并将结果显示在另一个列表中 例如: 清单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). 你就快到了。

我正试图编写一个prolog程序,对两个列表中的项求和,并将结果显示在另一个列表中

例如:

清单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).
你就快到了。 您的问题是,求和的结果应该放在第二个子句的开头,而不是递归调用中

list_sum([H1|T1],[H2|T2],[X|L3]):-list_sum(T1,T2,L3), X is H1+H2.
请注意,按照您编写它的方式,结果中“返回”的L3是一个列表,其中您从递归调用中删除了头(
X
);而您的意思正好相反:将一个元素(
X
)添加到结果列表中。

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

list_sum([H1|T1],[H2|T2],[X|L3]):-list_sum(T1,T2,L3), X is H1+H2.
请注意,按照您编写它的方式,结果中“返回”的L3是一个列表,其中您从递归调用中删除了头(
X
);而您的意思正好相反:将元素(
X
)添加到结果列表中。

结果应该是一个列表,所以不能只说
X是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

结果应该是一个列表,所以不能只说
X是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的头匹配。所以它输出了@gusbro所说的
no

。此外,您需要重新安排操作顺序,并添加两个额外的特殊情况以处理不同长度的列表:

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是X+Y
),以便在递归之前对
Z
求值。这可以完成两件事:

  • 首先,它使谓词尾部递归,这意味着解决方案是迭代的,因此不会占用堆栈空间。在代码中,直到整个递归完成后才执行求值。每个中间总和都保存在堆栈上,并在备份过程中从右向左求值。这意味着您将在一个大的列表中耗尽您的堆栈

  • 第二,在递归之前评估每个结果意味着你很快就会失败。与结果不一致的第一个和将使整个操作失败。你的解决方案失败得很慢。考虑10000000个项目列表,其中第一个项目不与结果列表中的第一个项目相加:你将遍历所有10000000个项目,然后假设你没有吹过你的堆栈-你开始从右向左求值。直到最后一次求值,您的谓词才会失败


    • 古斯布罗说了些什么。此外,您需要重新安排操作顺序,并添加两个额外的特殊情况以处理不同长度的列表:

      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是X+Y
      ),以便在递归之前对
      Z
      求值。这可以完成两件事:

      • 首先,它使谓词尾部递归,这意味着解决方案是迭代的,因此不会占用堆栈空间。在代码中,直到整个递归完成后才执行求值。每个中间总和都保存在堆栈上,并在备份过程中从右向左求值。这意味着您将在一个大的列表中耗尽您的堆栈

      • 第二,在递归之前评估每个结果意味着你很快就会失败。与结果不一致的第一个和将使整个操作失败。你的解决方案失败得很慢。考虑10000000个项目列表,其中第一个项目不与结果列表中的第一个项目相加:你将遍历所有10000000个项目,然后假设你没有吹过你的堆栈-你开始从右向左求值。直到最后一次求值,您的谓词才会失败


      如果您使用SWI Prolog,您可以使用maplist,在那里可以找到模块lambda::


      如果使用SWI Prolog,则可以使用maplist,并在其中找到模块lambda::


      这是SWI序言中的一行:

      list_sum(X,Y,S) :- maplist(plus, X,Y,S).
      
      它也“向后”工作:

      ?- maplist(plus, [1,2,3],Y,[3,4,5]).
      Y = [2, 2, 2].
      

      这是SWI序言中的一行:

      list_sum(X,Y,S) :- maplist(plus, X,Y,S).
      
      它也“向后”工作:

      ?- maplist(plus, [1,2,3],Y,[3,4,5]).
      Y = [2, 2, 2].
      

      @NicholasCarey:同意你的最后一条,我只是想展示一下OPs的问题,并在不改变他解决问题的方式的情况下进行修复。我不同意你的第二条和第三条,当列表长度不同时,程序会成功。这取决于要求,不是吗?@NicholasCarey:是的,但是我不能从他的问题推断出OPs要求。@NicholasCarey:同意你的最后一条,我只是想向他展示这个问题,并在不改变他解决问题的方式的情况下进行修复。我不同意你的第二条和第三条,当列表长度不同时,程序会成功。这取决于要求,不是吗?@NicholasCarey:是的,但是我不能从他的问题推断出那些符合OPs要求的人。“直到最后一次评估”。。。那可能是/应该是第一次回答得好!“直到最后一次评估”。。。那可能是/应该是第一次回答得好!它是内置的YAP。PIT是内置的YAP