Мы можем решить вашу проблему d сохранить logical-purity!
В следующем объявлении 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]
. Глядя на ответ на запрос выше, мы видим, что все, что нам нужно сделать, это карта [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] - хвостовой список. Обновление: о, вы уже его отредактировали. –
@EugeneSh. Фактически это была ошибка, когда я попытался упростить свой код к основной проблеме, а не полную ее реализацию, что он содержит больше предикатов, которые не имеют отношения к проблеме. – JmRag
В вашем базовом случае 'append' вам нужно« append ([], Y, [Y]) ». Если я правильно понимаю, это намерение. –