开发者

Prolog: Reverse every second list elements in a list

I have to write a progra开发者_如何学编程m that will get lists in a list, and should reverse every second list, then return the result. Something like this:

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

R = [[1,2], [4,3], [5,6], [8,7]]

This is what I have so far:

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

My problem is that, in the second iteration the add function fails. I'm also concerned about what will happen when the original list contains only one list at the end.


since you said that add/3 fails after the second iteration i assume that you used trace/0
anyway, here it is:

[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.

so why does it fail? it's because of one of prolog's main characteristics basically, a variable in prolog, once it takes a value, it can never change this may sound kinda weird if you used imperative languages so far but consider that exactly the same thing happens in math.
For example, consider the following equations:

x+3=4  
4-x=5

from the first we get that x=1
and from the second we get that x=-1
since x cannot be 1 and -1 we say that there is no x to satisfy the equations above;
not that x is -1 since that's the value of the second (and last) equation

exactly the same thing happens in yout program:

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

so the first time R is assigned a value and the doStuff/2 is call with a value for R.
obviously, this is not the correct value so doStuff/2 fails

so how can you fix this? look at the way you wrote [X,S|T] to separate the first two elements that you wanted to process. you only have to do exactly the same with the result:
write it like [XResult,SResult|Rest] of course XResult will be simply X and SResult will be the reverse of S (Rev)
Rest will be what you get from the recursive call of doStuff/2

last but not least you should check the clauses that are called in the end.

you could check some stuff about lists and recursion

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜