Prolog 序言:在列表中每秒反转一次列表元素

Prolog 序言:在列表中每秒反转一次列表元素,prolog,Prolog,我必须编写一个程序,将列表中的列表,并应每秒钟反转一次列表,然后返回结果。大概是这样的: doStuff([[1,2], [3,4], [5,6], [7,8]], R). R = [[1,2], [4,3], [5,6], [8,7]] 这就是我到目前为止所做的: doStuff([],_). doStuff([X,S|T],R):- reverse(S,Rev), add(X,Rev,R), doStuff(T,R). doStuff([X|[]], R):- add(X,R,R).

我必须编写一个程序,将列表中的列表,并应每秒钟反转一次列表,然后返回结果。大概是这样的:

doStuff([[1,2], [3,4], [5,6], [7,8]], R).

R = [[1,2], [4,3], [5,6], [8,7]]
这就是我到目前为止所做的:

doStuff([],_).
doStuff([X,S|T],R):- reverse(S,Rev), add(X,Rev,R), doStuff(T,R).
doStuff([X|[]], R):- add(X,R,R).

reverse([X|Y],Z,W) :- reverse(Y,[X|Z],W).
reverse([],X,X).

add(X,[],X).
add(X,L,[X,L]).
我的问题是,在第二次迭代中,add函数失败。
我还担心当原始列表末尾只包含一个列表时会发生什么情况。

因为您说过add/3在第二次迭代后失败,所以我假设您使用了trace/0 无论如何,这是:

[trace]  ?- doStuff([[1,2], [3,4], [5,6], [7,8]], R).
   Call: (6) doStuff([[1, 2], [3, 4], [5, 6], [7, 8]], _G405) ? creep
   Call: (7) lists:reverse([3, 4], _G496) ? creep
   Exit: (7) lists:reverse([3, 4], [4, 3]) ? creep
   Call: (7) add([1, 2], [4, 3], _G405) ? creep
   Exit: (7) add([1, 2], [4, 3], [[1, 2], [4, 3]]) ? creep
   Call: (7) doStuff([[5, 6], [7, 8]], [[1, 2], [4, 3]]) ? creep
   Call: (8) lists:reverse([7, 8], _G514) ? creep
   Exit: (8) lists:reverse([7, 8], [8, 7]) ? creep
   Call: (8) add([5, 6], [8, 7], [[1, 2], [4, 3]]) ? creep
   Fail: (8) add([5, 6], [8, 7], [[1, 2], [4, 3]]) ? creep
   Redo: (7) doStuff([[5, 6], [7, 8]], [[1, 2], [4, 3]]) ? creep
   Fail: (7) doStuff([[5, 6], [7, 8]], [[1, 2], [4, 3]]) ? creep
   Redo: (6) doStuff([[1, 2], [3, 4], [5, 6], [7, 8]], _G405) ? creep
   Fail: (6) doStuff([[1, 2], [3, 4], [5, 6], [7, 8]], _G405) ? creep
false.
那么为什么它会失败呢?这是因为prolog的一个主要特点 基本上,prolog中的一个变量,一旦它取了一个值,它就永远不会改变 这听起来有点奇怪,如果你使用命令式语言到目前为止,但认为完全相同的事情发生在数学。 例如,考虑下列方程:

x+3=4  
4-x=5
从一开始我们得到x=1 从第二秒开始,我们得到x=-1 因为x不能是1和-1,我们说没有x满足上面的方程; 不是x是-1,因为这是第二个也是最后一个等式的值

在yout计划中也会发生同样的事情:

doStuff([X,S|T],R):- reverse(S,Rev), add(X,Rev,R), doStuff(T,R).
因此,第一次为R赋值,并使用R的值调用doStuff/2。 显然,这不是正确的值,因此doStuff/2失败

那么你怎么能解决这个问题呢?看看你写[X,S|T]的方式,它将你想要处理的前两个元素分开。您只需对结果执行完全相同的操作: 像[XResult,SResult | Rest]那样写 当然,XResult将只是X,SResult将与S Rev相反 Rest将是您从doStuff/2的递归调用中得到的

最后但并非最不重要的一点是,您应该检查最后调用的子句


你可以查一些关于和的资料

你好。谢谢你的回答。在过去的几天里,我一直在努力实现它。所以我的问题是,当add函数试图更改R变量时,它在第二次迭代中已经有了一个值。所以我需要使用临时变量。这是我根据你的回答写的。它返回但不返回结果列表。doStuff[X,S|T],R:-反向,修订,添加,修订,[XResult,SResult | Rest],doStuff[XResult,SResult | Rest]。我做错了什么?再次感谢。您不应该将XResult,SResult传递给doStuff/2的递归调用,而应该调用doStuff,Rest。结果列表是R,因此您应该定义R是什么。例如,您可以编写R=[X,Rev | Rest]。所以基本上你有这个:doStuff[X,S | T],R:-反转,Rev,doStuff,Rest,R=[X,Rev | Rest]。因为你不在其他地方使用R,你可以简单地写:doStuff[X,S | T],[X,Rev | Rest]:-reverseS,Rev,doStuff,Rest。好的,现在我明白你之前的意思了,不需要add函数。谢谢,我真的很感激。