私たちはあなたの問題に取り組み、論理的純粋性を維持することができます!
以下では、質問で使用したリストを としますXs
。[1,1,1,2,2,2,3,1,1]
最初に、 のすべてのリストにから取得した等しい要素のみが含まれるようXs
に、リストのリストにマップします。具体化された不等式述語と連携してメタ述語を使用することにより、これを行います。Yss
Ys
Yss
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]
です。上記のクエリの答えを見ると、 to 、to 、to 、toにマップするだけでよいことがわかります。まさにそれを行います:[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).
meta-predicate の助けを借りて、 の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
はmonotoneであるため、根拠のない用語を扱っている場合でも、論理的に正しい答えが得られます。実際に見てみましょう!
?- 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]].