计算相同的元素Prolog

时间:2014-10-17 03:37:30

标签: list prolog

我想计算列表中的一个元素并停止计算不同元素出现的位置,然后跳转到下一个相同的元素。

答案应该是这样的:

?- count(a,[a,a,a,a,b,a,a,a],X).
X = [4,3]

?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],X).
X = [3,1,2,4]

我为count/3撰写的代码是:

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

我不知道如何让它返回一个数字列表。 谁能帮我? 感谢。

2 个答案:

答案 0 :(得分:3)

以下是您可以执行此操作并保留的方法!

在下文中,我们使用元谓词(splitlistIfAdj/3tfilter/3,和 maplist/3)和具体术语平等/不等式谓词((=)/3dif/3)。

让我们一步一步地E = aXs0 = [a,a,a,b,a,b,a,a,b,a,a,a,a]并建立count/3

  1. 首先,让Xs1包含Xs0中项目的运行:  

    ?- Xs0 = [a,a,a,b,a,b,a,a,b,a,a,a,a], splitlistIfAdj(dif,Xs0,Xs1).
    Xs0 = [ a,a,a,  b,  a,  b,  a,a,  b,  a,a,a,a ],
    Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]].
    

  2. 运行列表Xs1包含所有运行。让Xs2仅包含我们感兴趣的内容:  

    ?- Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]], tfilter(\[X|_]^(X=a),Xs1,Xs2).
    Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]],
    Xs2 = [[a,a,a],    [a],    [a,a],    [a,a,a,a]].
    

  3. 差不多完成了!最后,我们将Xs2E - 运行列表)映射到相应的运行长度Xs:  

    ?- Xs2 = [[a,a,a],[a],[a,a],[a,a,a,a]], maplist(length,Xs2,Xs).
    Xs2 = [[a,a,a],[a],[a,a],[a,a,a,a]],
    Xs  = [      3,  1,    2,        4].
    

  4. 现在,让我们把它们放在一起!

    count(E,Xs0,Xs) :-
        splitlistIfAdj(dif,Xs0,Xs1),
        tfilter(E+\[X|_]^(X=E),Xs1,Xs2),   % works for _any_ item E
        maplist(length,Xs2,Xs).
    

    让我们运行一些查询:

    ?- count(a,[a,a,a,a,b,a,a,a],Xs).
    Xs = [4,3].                            % succeeds deterministically
    ?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],Xs).
    Xs = [3,1,2,4].                        % succeeds deterministically
    

    由于代码单调,我们也会获得逻辑上合理的答案以获取更多常规查询:

    ?- count(E,[a,a,a,b,a,b,a,a,b,a,a,a,a],Xs).
    Xs = [3,1,2,4], E = a              ;
    Xs = [1,1,1],   E = b              ;
    Xs = [],        dif(E,a), dif(E,b) .
    

答案 1 :(得分:1)

我的回答中的想法是保持run lengths列表打开,并在运行结束时为其添加新元素:

count(_, [], []).
count(Item, [Head|Tail], Counts) :-
    count(Item, [Head|Tail], 0, Counts).
count(_, [], CurrentCount, [CurrentCount]).

count(Item, [Item|Tail], CurrentCount, Counts) :-
    CurrentCountP1 is CurrentCount + 1,
    count(Item, Tail, CurrentCountP1, Counts).
count(Item, [Head|Tail], CurrentCount, [CurrentCount|Counts]) :-
    dif(Head, Item),
    count(Item, Tail, 0, Counts).
?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a], X).
X = [3, 1, 2, 4] ;
false.