2016-02-07 76 views
0

很可能我無法恰當地使用我的搜索關鍵字。我想要做的是遞歸評估列表中連續條目的差異,並不斷將它們添加到全局計數器中。挑戰是最後的通告條款,因此如果列表是[5,4,3,2,1],謂詞應該返回(5-4)+(4-3)+(3-2)+(2-1)+(1-5)=0序言:使用一次性規則在列表中遞歸

我至今如下:

circularSumOfDifferences([_],0). 
circularSumOfDifferences([E1,E2|List],Sum) :- 
    Diff is E1-E2, 
    circularSumOfDifferences([E2|List],SoD), 
    Sum is Diff+SoD. 

現在我已經想定義另一個謂詞在給定列表的尾部添加列表中的第一個元素,並要求結合新名單查詢:copyHeadToTail([5,4,3,2,1],Result),circularSumOfDifferences(Result,C).

這不難實現,但對我來說看起來並不高雅。我想知道是否有一種方法可以定義一個謂詞circularSumOfDifferences(+L,-SoD),該謂詞circularSumOfDifferences(+L,-SoD)通過列表遞歸併在最後(或開始)爲該一個減法運行一個語句, 1-5

回答

3

你可以寫一個謂詞,這樣做,當然,但你應該已經注意到,名單中的每個元素X在總和中出現兩次,一次是X,一次作爲-X。無論您給出這個謂詞的數字列表如何,您總會得到0。這是一項功課嗎?這是非常有可能的一點是要注意的,而不是試圖計算出實際的總和此:

always_zero([], 0). 
always_zero([X|Xs], 0) :- 
    number(X), 
    always_zero(Xs, 0). 

這裏是你可能想怎麼寫謂詞,如果你堅持:

circ_sum_of_diff([X|Xs], Sum) :- % must have at least one element I guess? 
    circ_sum_of_diff_1(Xs, X, X, 0, Sum). 

circ_sum_of_diff_1([], Last, First, SoFar, Sum) :- 
    Sum is SoFar + Last - First. 
circ_sum_of_diff_1([X|Xs], X0, First, SoFar0, Sum) :- 
    SoFar is SoFar0 + X0 - X, 
    circ_sum_of_diff_1(Xs, X, First, SoFar, Sum). 

這使用一個輔助謂詞,這在Prolog程序中非常常見。實際上在列表上迭代的輔助謂詞有三個附加參數:列表的未壓縮的頭部,原始的第一個元素(在列表的末尾使用)和迄今爲止的總和。

+0

感謝您向我介紹輔助謂詞,這正是我想要的。我可能較早見過它,但從未將它包含在我的工具箱中。順便說一句,我從TSP問題中解釋了我的問題,其中列表將包含要訪問的城鎮,因此推銷員必須在最後一個城鎮之後到達第一個城鎮。我通常會說出這樣的定製問題,以便成功返回0。 – Donbhupi

+0

@Donbhupi我不完全理解你的評論。 「成功返回」任何東西都沒有意義。另外,如果你需要製作一個像[a-b,b-c,...]這樣的術語,你絕對不需要任何算術和數字,這可能會使我的答案無效。 –

+0

考慮到它是Prolog,將'return'讀爲'評估爲0'。實際謂詞包含城鎮名單[A,B,C,D],並調用另一個謂詞來計算哈密頓距離。我只是將這個問題改寫爲簡單無用的算術,以理解它在Prolog中是如何完成的。 – Donbhupi