2014-10-17 46 views
3

我想計算列表中的一個元素並停止計算不同元素出現的位置,並跳轉到下一個相同的元素。計數相同的元素Prolog

的答案應該是這樣的:

?- count(a,[a,a,a,a,b,a,a,a],X). 
X = [4,3] 

?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],X). 
X = [3,1,2,4] 

我寫了count/3的代碼是:

count(_, [], []). 
count(X, [X | T], N) :- 
    count(X, T, N1), 
    !, 
    N is N1 + 1. 
count(X, [_ | T], N) :- 
    count(X, T, N). 

我不知道如何使它返回數列表。 任何人都可以幫助我嗎? 謝謝。

+2

你的問題相當模糊,所以我只給出一個提示:使用4個參數而不是3:2作爲輸入,1作爲輸出,1作爲當前麻木呃找到的元素(初始爲0)。 – Steven 2014-10-17 03:50:28

+0

@Kay,實際上我輸入的列表只包含兩個不同的元素,我想計算一個,如果它,結果應該只計算該元素。例如輸入計數(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],X)。並輸出 X = [3,1,2,4] – 2014-10-17 08:35:56

回答

1

在我回答這個想法是保持run lengths開放的名單,並添加了新的元素,它在運行結束:

count(_, [], []). 
count(Item, [Head|Tail], Counts) :- 
    count(Item, [Head|Tail], 0, Counts). 
count(_, [], CurrentCount, [CurrentCount]). 

count(Item, [Item|Tail], CurrentCount, Counts) :- 
    CurrentCountP1 is CurrentCount + 1, 
    count(Item, Tail, CurrentCountP1, Counts). 
count(Item, [Head|Tail], CurrentCount, [CurrentCount|Counts]) :- 
    dif(Head, Item), 
    count(Item, Tail, 0, Counts). 
?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a], X). 
X = [3, 1, 2, 4] ; 
false. 
+0

是啊,這正是我想要得到的,謝謝 – 2014-10-18 01:17:05

+0

從'count/3'到'count/4'時,可以將輸入列表移動到第一個參數,並使用if-then-else組合'count/4'的最後兩個子句。這將消除示例查詢中出現的虛假選擇點(當然,假設第一個參數索引在大多數系統中是典型的)。 – 2015-05-14 10:11:04

3

這裏是你如何能做到這一點,保存

在下文中,我們使用元謂詞(splitlistIfAdj/3tfilter/3maplist/3)和物化長期等號/不等謂詞((=)/3dif/3)。

讓我們E = aXs0 = [a,a,a,b,a,b,a,a,b,a,a,a,a],並建立count/3一步一步:

  1. 首先,讓Xs1包含運行項目Xs0

     
    ?- Xs0 = [a,a,a,b,a,b,a,a,b,a,a,a,a], splitlistIfAdj(dif,Xs0,Xs1). 
    Xs0 = [ a,a,a, b, a, b, a,a, b, a,a,a,a ], 
    Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]]. 
    

  2. 運行Xs1名單包含全部運行。假設Xs2只包含我們感興趣的產品:

     
    ?- Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]], tfilter(\[X|_]^(X=a),Xs1,Xs2). 
    Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]], 
    Xs2 = [[a,a,a], [a], [a,a], [a,a,a,a]]. 
    

  3. 幾乎完成!最後,我們繪製Xs2(的E -runs列表)到相應的運行長度Xs

     
    ?- Xs2 = [[a,a,a],[a],[a,a],[a,a,a,a]], maplist(length,Xs2,Xs). 
    Xs2 = [[a,a,a],[a],[a,a],[a,a,a,a]], 
    Xs = [  3, 1, 2,  4]. 
    

現在,讓我們把它放在一起!

 
count(E,Xs0,Xs) :- 
    splitlistIfAdj(dif,Xs0,Xs1), 
    tfilter(E+\[X|_]^(X=E),Xs1,Xs2), % works for _any_ item E 
    maplist(length,Xs2,Xs). 

讓我們運行一些查詢:

?- count(a,[a,a,a,a,b,a,a,a],Xs). 
Xs = [4,3].       % succeeds deterministically 
?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],Xs). 
Xs = [3,1,2,4].      % succeeds deterministically 

由於代碼單調,我們得到更普遍的查詢邏輯的聲音回答,太:

?- count(E,[a,a,a,b,a,b,a,a,b,a,a,a,a],Xs). 
Xs = [3,1,2,4], E = a    ; 
Xs = [1,1,1], E = b    ; 
Xs = [],  dif(E,a), dif(E,b) .