2014-11-20 2 views
2

Здравствуйте Я пытаюсь сделать программу в Прологе, что данный список он подсчитывает число вхождений каждого последующего элемента в списке следующим образом:подсчет последовательных вхождений числа в Прологе

count(1,[1,1,1,2,2,2,3,1,1],0,X) 

результат будет X=[ [1,3],[2,3],[3,1][1,2] ] aka каждый подсписок [element,occurrences]

В моем случае я считаю, что что-то не так с базовым корпусом, но я не могу его решить. Вы можете мне помочь?

%append an element to a list 
append([ ],Y,Y). 
append([X|Xs],Ys,[X|Zs]):-append(Xs,Ys,Zs). 

%c is the counter beginning with 0 
count(_,[],_,[]). 
count(X,[X],C,[L]):-count(X,[],C,[L|[X,C]]). 

%increase counter 
count(X,[X|Tail],C,L):-Z is C+1,count(X,Tail,Z,L). 
count(X,[Head|Tail],C,[L]):-append(L,[X,C],NL),count(Head,Tail,1,NL). 
+0

Я могу видеть по крайней мере одна проблема: '[L | [X, C]]' произведет простой список. L - это голова (один элемент), а [X, C] - хвостовой список. Обновление: о, вы уже его отредактировали. –

+0

@EugeneSh. Фактически это была ошибка, когда я попытался упростить свой код к основной проблеме, а не полную ее реализацию, что он содержит больше предикатов, которые не имеют отношения к проблеме. – JmRag

+0

В вашем базовом случае 'append' вам нужно« append ([], Y, [Y]) ». Если я правильно понимаю, это намерение. –

ответ

2

Еще одна попытка сделать ru n-length, на основе !

 
:- use_module(library(clpfd)). 

на основе if_/3 и (=)/3, мы определяем list_rle/2:

 
list_rle([],[]). 
list_rle([X|Xs],[N*X|Ps]) :- 
    list_count_prev_runs(Xs,N,X,Ps). 

list_count_prev_runs(Es,N,X,Ps) :- 
    N #> 0, 
    N #= N0+1, 
    list_count_prev_runs_(Es,N0,X,Ps). 

list_count_prev_runs_([],0,_,[]). 
list_count_prev_runs_([E|Es],N,X,Ps0) :- 
    if_(X=E, 
     list_count_prev_runs(Es,N,X,Ps0), 
     (N = 0, Ps0 = [M*E|Ps], list_count_prev_runs(Es,M,E,Ps))). 

Примеры запросов:

  • кодирования/декодирования # 1

     
    ?- list_rle([a,a,b,c,c,c,d,e,e],Ys). 
    Ys = [2*a,1*b,3*c,1*d,2*e]. 
    
    ?- list_rle(Xs,[2*a,1*b,3*c,1*d,2*e]). 
        Xs = [a,a,b,c,c,c,d,e,e] 
    ; false. 
    
  • кодирования/декодирования # 2

     
    ?- dif(A,B),dif(B,C),dif(C,D),dif(D,E), list_rle([A,A,B,C,C,C,D,E,E],Ys). 
    Ys = [2*A,1*B,3*C,1*D,2*E], dif(A,B), dif(B,C), dif(C,D), dif(D,E). 
    
    ?- list_rle(Xs,[2*A,1*B,3*C,1*D,2*E]). 
        Xs = [A,A,B,C,C,C,D,E,E], dif(A,B), dif(B,C), dif(C,D), dif(D,E) 
    ; false. 
    
  • Как о чем-то немного больше общего?

     
    ?- list_rle([A,B,C,D],Xs). 
        Xs = [4*A   ],  A=B ,  B=C ,  C=D 
    ; Xs = [3*A,  1*D],  A=B ,  B=C , dif(C,D) 
    ; Xs = [2*A, 2*C ],  A=B , dif(B,C),  C=D 
    ; Xs = [2*A, 1*C,1*D],  A=B , dif(B,C), dif(C,D) 
    ; Xs = [1*A,3*B  ], dif(A,B),  B=C ,  C=D 
    ; Xs = [1*A,2*B, 1*D], dif(A,B),  B=C , dif(C,D) 
    ; Xs = [1*A,1*B,2*C ], dif(A,B), dif(B,C),  C=D 
    ; Xs = [1*A,1*B,1*C,1*D], dif(A,B), dif(B,C), dif(C,D). 
    
+0

Так что теоретически было бы лучше для '? - list_rle (Xs, [2 * a, 1 * b, 3 * c, 1 * d, 2 * e]). Xs = [a, a, b, c, c, c, d, e, e] ; false.' быть детерминированным? и у вас нет точки выбора? – user27815

+0

@ пользователь27815. Это было бы. Но мы должны добиться баланса и расставить приоритеты: правильность> универсальность> эффективность. – repeat

1

Почему вы указываете связь между двумя списками с предикатом, имеющим 4 аргумента? Давайте попробуем шаг за шагом.

Пустой список дает пустой список, элемент подсчитываются получает приращение, в противном случае, начать отсчет ...

count([],[]). 
count([X|T],[[X,C1]|R]) :- count(T,[[X,C]|R]), !, C1 is C+1. 
count([X|T],[[X,1]|R]) :- count(T,R). 

?- count([1,1,1,2,2,2,3,1,1],R). 
R = [[1, 3], [2, 3], [3, 1], [1, 2]]. 

так легко (конечно, при условии X = [[1,3], [2 , 3], [1,3] [1,2]] это опечатка ...)

+0

Ничего себе, ваш ответ заставил меня выглядеть идиотом. Я еще не очень хорошо знаком с прологом, и я думаю, что я буду заниматься децилераторным программированием. Thx много для вашего ответа и объяснения! Да, то, что вы указываете жирным шрифтом, является опечаткой, я отредактировал вопрос, чтобы быть правильным. – JmRag

0

Другое решение (хвостовая рекурсия) заключается в следующем:

run_length_encode(Xs , Ys) :- % to find the run length encoding of a list , 
    rle(Xs , 1 , Ys) .   % - just invoke the helper 

rle([]  , _ , [] ) .  % the run length encoding of the empty list is the empty list 
rle([A]  , N , [X:N]) .  % A list of length 1 terminates the run: move the run length to the result 
rle([A,A|Xs] , N , Ys ) :- % otherwise, if the run is still going 
    N1 is N+1 ,      % - increment the count, 
    rle([A|Xs] , N1 , Ys)   % - and recurse down 
    .        % 
rle([A,B|Xs] , N , [A:N|Ys]) :- % otherwise, if the run has ended 
    A \= B ,      % - we have a break 
    rle([B|Xs] , 1 , Ys)   % - add the completed run length to the result and recurse down 
    .        % 
2

Мы можем решить вашу проблему d сохранить !

В следующем объявлении 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]]. 
0

Если мы пропускаем использование «является» мы можем иметь решение, как:

precondition(Clause):- 
    Clause =.. [_|ARGS], 
    (maplist(var,ARGS) -> true; Clause). 

count([], []). 

count([X], [(X,1)]) :- !. 

count([H|Q], [(H,1),(HR,NR)|QR]) :- 
    count(Q, [(HR,NR)|QR]), 
    H \= HR, 
    !. 

count([H|Q], [(H,NR)|QR]) :- 
    precondition(succ(N,NR)), 
    count(Q, [(H,N)|QR]), 
    succ(N,NR). 

, что позволяет не только обычный запрос:

[debug] ?- count([1,1,1,2,2,2,3,1,1],R). 
R = [ (1, 3), (2, 3), (3, 1), (1, 2)]. 

, но и наоборот, один:

[debug] ?- count(X, [ (1, 3), (2, 3), (3, 1), (1, 2)]). 
X = [1, 1, 1, 2, 2, 2, 3, 1, 1]. 
Смежные вопросы