2014-06-04 197 views
0

我正在使用Prolog示例列表程序和triying對它們執行一些操作。但是,我被困在一個點上,找不到任何解決方案或樣本。Prolog迭代列表

我想寫一個函數,它需要兩個整數列表並返回一個浮點值。這兩個列表大小是相等的。浮點值是比較結果除以列表大小。

函數應該比較第一列表的每個元素和第二列表的每個元素。一對(i,j)是我是第一個列表中元素的位置,j是第二個列表中元素的位置。如果元素i大於元素j,則比較結果增加1.如果元素i小於元素j,則比較結果減1。如果相等,則不發生任何事情。在上述操作結束時,我們返回上面描述的浮點值。

實施例:

retVal([4,5,3], [8,2,1], Result). 

應返回結果=( - 1 + 1 + 1-1 + 1 + 1-1 + 1 + 1)/ 3 = 0.33

在面向對象的語言,它就像在控制檯上打印一樣簡單。不過,我對Prolog沒有任何想法。先謝謝你。

+0

你是什麼意思'結果列表應該返回參數列表的所有索引。 – Shevliaskovic

+0

我需要列表中的每個元素位置,以便稍後我可以將索引列表用於其他目的。實際上,我想遍歷參數列表並對每個元素執行一些操作。 – nudaStck

+0

舉個更多的例子... – false

回答

0

你描述的話可能是這個片段

retVal(L1,L2, Result) :- 
findall(S, (member(X1,L1), member(X2,L2), (X1 < X2 -> S = -1 ; S = 1)), L), 
sum_list(L, Sum), 
length(L1, Len), 
Result is Sum/Len. 

唉什麼,測試結果不符合您的期望

?- retVal([4,5,3], [8,2,1], X). 
X = 1. 

由於liori在他的評論中指出的那樣,你的手工計算是不正確的...

+0

retVal([1],[1],R)肯定應該是零,也就是0.0而不是> 0。 – false

+0

謝謝你的答案是如此的有用。現在我有另一個問題。我怎樣才能到達兩個列表中的一對元素? L1 = [1,2,3],L2 = [3,2,5]。 Pair(a,b)被確定爲L1中元素的位置,b是L2中元素的位置。所有可能的L1和L2對是:(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0) ,(2,1),(2,2)。我怎樣才能得到由兩個列表L1和L2構成的對列表?謝謝。 – nudaStck

+0

嘗試使用[nth0](http://www.swi-prolog.org/pldoc/doc_for?object=nth0/3)而不是成員。當然還需要其他一些改變。我希望你有使用findall/3的想法 – CapelliC

0

我認爲這應該工作:

sgn(X, Y, -1) :- X<Y. 
sgn(X, Y, 1) :- X>Y. 
sgn(X, X, 0). 

ssapd(L, R, O) :- ssapd(L, R, R, 0, 0, O). 
ssapd([LI | LR], RL, [RPI | RPL], ACC, ACCL, O) :- 
    sgn(LI, RPI, SGN), !, 
    ACC1 is ACC + SGN, 
    ssapd([LI | LR], RL, RPL, ACC1, ACCL, O). 
ssapd([_ | LR], RL, [], ACC, ACCL, O) :- 
    ACCL1 is ACCL + 1, 
    ssapd(LR, RL, RL, ACC, ACCL1, O). 
ssapd([],  _, _, ACC, ACCL, Result) :- 
    Result is ACC/ACCL. 

這是一個很好的實現與尾遞歸通過使用兩個累加器,O(N²)的時間複雜度和恆定的內存(除輸入的大小)來完成。要執行它,嘗試:

ssapd([4,5,3], [8,2,1], Result). 
0

這是一個尾遞歸的方法:

compare_list(Xs , Ys , Z) :- 
    compare_list(Xs, Ys, 0 , 0 , S , L) , 
    Z is float(S)/float(L) 
    . 

compare_list([]  , []  , S , L , S , L) . 
compare_list([X|Xs] , [Y|Ys] , A , B , S , L) :- 
    A1 is A + sign(X-V) , 
    B1 is B + 1 , 
    compare_list(Xs,Ys,A1,B1,S,L) 
    . 

另一種方法,這一次 「頭遞歸」:

compare_list(Xs , Ys , Z) :- 
    compare_list(Xs , Ys , S , L) , 
    Z is float(S)/float(L) 
    . 

compare_list([]  , []  , 0 , 0) . 
compare_list([X|Xs] , [Y|Ys] , S , L) :- 
    compare_list(Xs,Ys,S1,L1) , 
    S is S1 + sign(X-Y) , 
    L is L1 + 1 
    . 

前者實現贏得」 t在長列表上堆棧溢出,因爲它被優化爲[有效]迭代,但需要累加器;後者的實現不需要累加器,但是如果列表的長度足夠的話,會使堆棧崩潰。