计算并删除列表中第一个元素的连续出现次数

时间:2015-12-30 22:24:50

标签: list prolog

我想计算并删除列表中第一个元素的连续出现次数。

?- count([1,1,1,2,2,1], N, X, L). 
N = 3, X = 1, L = [2,2,1].               % expected answer

我试试这个:

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

3 个答案:

答案 0 :(得分:4)

以下是使用if_/3(=)/3执行此操作的方式:

count([], 0, _, []).
count([E|Es], N, E, L) :-
   skip_(Es, 1,N, E, L).

skip_([], N,N, _, []).
skip_([E|Es], N0,N, X, Xs) :-
   if_(E = X,
       ( N1 is N0+1, skip_(Es,N1,N,X,Xs) ),
       ( N0 = N,     Xs = [E|Es] )).

示例查询:

?- count([1,1,1,2], N, X, L).
N = 3, X = 1, L = [2].

?- count([1,1,1,2,2,1], N, X, L).
N = 3, X = 1, L = [2,2,1].

?- count([1], N, X, L).
N = X, X = 1, L = [].

?- J = [_,_,_], count(J, N, X, L).
   J = [X, X, X], N = 3, L = []
;  J = [X, X,_A], N = 2, L = [_A]   , dif(_A,X)
;  J = [X,_A,_B], N = 1, L = [_A,_B], dif(_A,X).

请注意,count/4也可以处理包含非整数的列表:

?- count([a,a,a,b,b,c], N, X, L).
N = 3, X = a, L = [b,b,c].

答案 1 :(得分:3)

count([], 0, _, []).
count(J, N, X, L) :-
   J = [X|_],
   append(Xs, L, J),
   startsnot_with(L, X),
   maplist(=(X), Xs),
   length(Xs, N).

startsnot_with([], _).
startsnot_with([E|_], X) :-
   dif(E, X).

| ?- J = [_,_,_], count(J, N, X, L).
   J = [X,_A,_B], N = 1, L = [_A,_B], dif(_A,X)
;  J = [X,X,_A],  N = 2, L = [_A], dif(_A,X)
;  J = [X,X,X],   N = 3, L = []
;  false.

答案 2 :(得分:0)

热切的尝试:

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

产量

?- count([1,1,1,2,2,1], N, X, L).
N = 3,
X = 1,
L = [2, 2, 1].

编辑,因为我们有一个整数域,尝试使用CLP(FD) - 混合(?)到Prolog渴望评估

initials_count([X,X|T],N,X,L) :-
    N #= M+1,
    initials_count([X|T],M,X,L).
initials_count([X|T],N,E,T) :-
    N #<==> X #= E.
应该像

一样调用

?- once(initials_count([1,1,1,2,2,1], N, X, L)).

(用SWI-Prolog测试)

在GnuProlog中,应该是

initials_count([X|T],N,E,T) :-
    N #<=> X #= E.

如果你想避免@false注释中所示的问题,那么(第一个谓词的)最后一个子句的细化可能是

count(L,0,E,L) :- L == [] ; L == [F|_], F \== E.