2011-05-14 110 views
0

我必须编写一个程序,该列表将获取列表中的列表,并且应该颠倒每个第二个列表,然后返回结果。事情是这样的:序言:颠倒列表中的每个第二个列表元素

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]). 

我的问题是,在第二次迭代的附加功能失效。 我也关心当最初的列表最后只包含一个列表时会发生什么。

回答

0

,因为你说,添加第二个迭代后/ 3失败,我假设你使用的跟踪/ 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被分配的值,并且doStuff/2的呼叫值为R.
显然,这是不正确的值,所以doStuff/2失败

所以你怎么解决这个问题?看看你写[X,S | T]的方式来分离你想要处理的前两个元素。你只需要做与结果完全一样的结果:
写下来就像[XResult,SResult | Rest] 当然XResult只是X而SResult会是S(Rev)的反向
剩下的就是你从doStuff/2的递归调用中获得/ 2

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

你可以检查有关listsrecursion

+0

你好一些东西。感谢你的回答。过去几天我一直在努力实施它。 所以我的问题是,R函数变量在第二次迭代中已经有一个值,当add函数试图改变它时。所以我需要使用临时变量。这是我根据你的回答写的。它返回但不返回结果列表。 (X,S | T],R): - reverse(S,Rev),add(X,Rev,[XResult,SResult | Rest]),doStuff(T,[XResult,SResult | Rest]) 。 我在做什么错? 再次感谢。 – eidolon 2011-05-16 15:46:37

+0

您不应将XResult,SResult传递给doStuff/2 的递归调用,而只需调用doStuff(T,Rest)。结果列表是R,所以你应该定义R是什么。例如,你可以写R = [X,Rev | Rest]。所以基本上你有这样的结果: - reverse(S,Rev),doStuff(T,Rest),R = [X,Rev | Rest]。因为你不使用任何其他地方你可以简单地写: doStuff([X,S | T],[X,Rev | Rest]): - reverse(S,Rev),doStuff(T,Rest) 。 – 2011-05-16 17:05:36

+0

好吧,现在我明白你的意思了,不需要添加功能。谢谢,我真的很感激。 – eidolon 2011-05-16 18:15:31

相关问题