首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用prolog在带有交替符号的列表中获得结果?

如何使用prolog在带有交替符号的列表中获得结果?
EN

Stack Overflow用户
提问于 2021-03-12 04:01:12
回答 1查看 71关注 0票数 0

该程序将生成列表的交替结果。例如,{5,6,1}将是5-6+1.

代码语言:javascript
复制
alternate(L,X) :-
   alternate(L,0,K,_).

alternate([],X,_,_).

alternate([H|T],A,p,S) :- !,
    AA is A + H,
    alternate(T,AA,m,S).

alternate([H|T],A,m,S) :- !,
    AA is A - H,
        alternate(T,AA,p,S).

以下是跟踪结果:

代码语言:javascript
复制
alternate([5,6,1],S).
   Call: (10) alternate([5, 6, 1], _11626) ? creep
   Call: (11) alternate([5, 6, 1], 0, p, _12084) ? creep
   Call: (12) _12128 is 0+5 ? creep
   Exit: (12) 5 is 0+5 ? creep
   Call: (12) alternate([6, 1], 5, m, _12222) ? creep
   Call: (13) _12266 is 5-6 ? creep
   Exit: (13) -1 is 5-6 ? creep
   Call: (13) alternate([1], -1, p, _12360) ? creep
   Call: (14) _12404 is -1+1 ? creep
   Exit: (14) 0 is -1+1 ? creep
   Call: (14) alternate([], 0, m, _12498) ? creep//I expect it to return the X = 0 here.
   Exit: (14) alternate([], 0, m, _12542) ? creep
   Exit: (13) alternate([1], -1, p, _12586) ? creep
   Exit: (12) alternate([6, 1], 5, m, _12630) ? creep
   Exit: (11) alternate([5, 6, 1], 0, p, _12674) ? creep
   Exit: (10) alternate([5, 6, 1], _11626) ? creep
true.

当没有更多的元素时,我使用备用([],X,,)来返回X,但是我不明白为什么它不能工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-12 05:55:49

如果到达列表的末尾,则需要将累加器中迄今计算的值(第二个参数)短路为“最终结果”:

而不是:

代码语言:javascript
复制
alternate([],X,_,_).
代码语言:javascript
复制
alternate([],X,_,X).

启动时,从p开始,累加器设置为0。关于成功,论点4将包含最终结果:

代码语言:javascript
复制
alternate(L,X) :-
   alternate(L,0,p,X).

因此:

代码语言:javascript
复制
alternate(L,X) :-
   alternate(L,0,p,X).

alternate([],X,_,X).

alternate([H|T],A,p,S) :- !,
    AA is A + H,
    alternate(T,AA,m,S).

alternate([H|T],A,m,S) :- !,
    AA is A - H,
        alternate(T,AA,p,S).
代码语言:javascript
复制
?- alternate([1,2,3,4],X).
X = -2.

奖金:作为DCG

这一项是用非尾递归方式编写的,因此只需要对每个调用进行“最后和”,然后根据谓词成功计算一个新的“最后和”:

代码语言:javascript
复制
alternate(List,Sum) :- phrase(alternate_p(Sum),List).

alternate_p(0)   --> [].
alternate_p(Sum) --> [X], alternate_n(TailSum), { Sum is TailSum+X }.

alternate_n(0)   --> [].
alternate_n(Sum) --> [X], alternate_p(TailSum), { Sum is TailSum-X }.
代码语言:javascript
复制
?- alternate([1,2,3,4],Sum).
Sum = -2 ;  % any additional solutions?
false.      % nope

奖金:使用折叠/4

这一切都是以尾递归的方式在列表上积累一个值,我们可以避免自己编写递归,切换到“函数编码”并使用foldl/4。我们只需要编写一个谓词,这里的alternator/3为每个列表元素调用,从“左侧”获取“内容”,并构建“新内容”并将其移到“右边”。在我们的例子中,“[Sum,Multiplier]”是一对

代码语言:javascript
复制
% alternator(Element,FromLeft,ToRight)

alternator(Element,[Sum,Multiplier],[NewSum,NewMultiplier]) :-
   NewSum is Sum + Multiplier*Element,
   NewMultiplier is Multiplier*(-1).
   
% alternate(List,Sum) is an application of foldl/4:

alternate(List,Sum) :-
   foldl(alternator,List,[0,1],FoldlResult),
   FoldlResult = [Sum,_FinalMultiplier].

再一次:

代码语言:javascript
复制
?-  alternate([1,2,3,4],Sum).
Sum = -2.
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66594020

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档