2011-05-14 112 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

相關問題