2014-10-17 47 views
3

我想计算列表中的一个元素并停止计算不同元素出现的位置,并跳转到下一个相同的元素。计数相同的元素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

你的问题相当模糊,所以我只给出一个提示:使用4个参数而不是3:2作为输入,1作为输出,1作为当前麻木呃找到的元素(初始为0)。 – Steven 2014-10-17 03:50:28

+0

@Kay,实际上我输入的列表只包含两个不同的元素,我想计算一个,如果它,结果应该只计算该元素。例如输入计数(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],X)。并输出 X = [3,1,2,4] – 2014-10-17 08:35:56

回答

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. 
+0

是啊,这正是我想要得到的,谢谢 – 2014-10-18 01:17:05

+0

从'count/3'到'count/4'时,可以将输入列表移动到第一个参数,并使用if-then-else组合'count/4'的最后两个子句。这将消除示例查询中出现的虚假选择点(当然,假设第一个参数索引在大多数系统中是典型的)。 – 2015-05-14 10:11:04

3

这里是你如何能做到这一点,保存

在下文中,我们使用元谓词(splitlistIfAdj/3tfilter/3maplist/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. 几乎完成!最后,我们绘制Xs2(的E -runs列表)到相应的运行长度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]. 
    

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

 
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) .