count successive occurrences of number in Prolog

后端 未结 5 612
情深已故
情深已故 2021-01-23 05:57

Hello I am trying to make a program in Prolog that given a list it counts the occurrences of each successive element in the list as follows:

count(1,[1,1,1,2,2,2         


        
5条回答
  •  长发绾君心
    2021-01-23 06:47

    We can tackle your problem and preserve logical-purity!

    In the following let Xs be [1,1,1,2,2,2,3,1,1], the list you used in your question.

    First, we map Xs to a list of lists Yss such that every list Ys in Yss only contains equal elements taken from Xs. We do that by using the meta-predicate splitlistIfAdj/3 in tandem with the reified inequality predicate 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]].
    

    Second, we map the list of lists Yss to Zss. Each item in Zss has the form [Element,Amount]. Looking at the answer of above query, we see that all we need to do is map [1,1,1] to [1,3], [2,2,2] to [2,3], [3] to [3,1], and [1,1] to [1,2]. run_pair/2 does exactly that:

    run_pair(Ys,[Element,Amount]) :-
       Ys = [Element|_],
       length(Ys,Amount).
    

    Let's use run_pair/2 to map every item of Yss, with the help of meta-predicate 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]].
    

    Done! Time to put it all together:

    count(Xs,Zss) :-
       splitlistIfAdj(dif,Xs,Yss),
       maplist(run_pair,Yss,Zss).
    

    Let's see if above query still works :)

    ?- count([1,1,1,2,2,2,3,1,1],Zss).
    Zss = [[1,3],[2,3],[3,1],[1,2]].      % succeeds deterministically
    

    As the implementation of count/2 is monotone, we get logically sound answers even when working with non-ground terms. Let's see that in action!

    ?- 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]].
    

提交回复
热议问题