我們能夠解決您的問題一個d保存logical-purity!
下面讓我們Xs
爲[1,1,1,2,2,2,3,1,1]
,您在問題中使用的列表。
首先,我們映射到Xs
名單列表Yss
使得Yss
每個列表Ys
只包含來自Xs
採取相同的元素。 我們通過使用元謂詞splitlistIfAdj/3
亦隨物化的不平等謂詞dif/3
:
?- Xs = [1,1,1,2,2,2,3,1,1], splitlistIfAdj(dif,Xs,Yss).
Xs = [ 1,1,1, 2,2,2, 3, 1,1 ],
Yss = [[1,1,1],[2,2,2],[3],[1,1]].
二,我們映射列表Yss
到Zss
名單。 Zss
中的每個項目的格式爲[Element,Amount]
。 綜觀上述查詢的答案,我們可以看到,我們需要做的就是地圖[1,1,1]
到[1,3]
,[2,2,2]
到[2,3]
,[3]
到[3,1]
,並[1,1]
到[1,2]
。 run_pair/2
正是這麼做的:
run_pair(Ys,[Element,Amount]) :-
Ys = [Element|_],
length(Ys,Amount).
讓我們用run_pair/2
到Yss
每個項目地圖,與元謂詞maplist/3
的幫助:
?- Yss = [[1,1,1],[2,2,2],[3],[1,1]], maplist(run_pair,Yss,Zss).
Yss = [[1,1,1],[2,2,2],[3] ,[1,1]],
Zss = [[1,3], [2,3], [3,1],[1,2]].
完成!時間把它放在一起:
count(Xs,Zss) :-
splitlistIfAdj(dif,Xs,Yss),
maplist(run_pair,Yss,Zss).
讓我們看看上面的查詢仍然有效:)
?- count([1,1,1,2,2,2,3,1,1],Zss).
Zss = [[1,3],[2,3],[3,1],[1,2]]. % succeeds deterministically
由於count/2
實現是單調,我們得到與工作時邏輯聽起來答案甚至非基礎條款。讓我們看看在行動!
?- Xs = [A,B,C,D], count(Xs,Zss).
Xs = [D,D,D,D], A=B, B=C , C=D , Zss = [ [D,4]] ;
Xs = [C,C,C,D], A=B, B=C , dif(C,D), Zss = [ [C,3],[D,1]] ;
Xs = [B,B,D,D], A=B, dif(B,C), C=D , Zss = [ [B,2], [D,2]] ;
Xs = [B,B,C,D], A=B, dif(B,C), dif(C,D), Zss = [ [B,2],[C,1],[D,1]] ;
Xs = [A,D,D,D], dif(A,B), B=C , C=D , Zss = [[A,1], [D,3]] ;
Xs = [A,C,C,D], dif(A,B), B=C , dif(C,D), Zss = [[A,1], [C,2],[D,1]] ;
Xs = [A,B,D,D], dif(A,B), dif(B,C), C=D , Zss = [[A,1],[B,1], [D,2]] ;
Xs = [A,B,C,D], dif(A,B), dif(B,C), dif(C,D), Zss = [[A,1],[B,1],[C,1],[D,1]].
我至少可以看到一個問題就在這裏:'[L | [X,C]]'會產生一個普通列表。 L是頭(單個元素),[X,C]是尾部列表。更新:哦,你已經編輯它.. – 2014-11-20 21:16:28
@EugeneSh。實際上,當我試圖將我的代碼簡化爲基本問題而不是完全實現它時,它包含了更多與問題無關的謂詞。 – JmRag 2014-11-20 21:20:52
在你的'append'基本情況下,你需要'append([],Y,[Y])。'如果我明白它的意圖。 – 2014-11-20 21:26:56