【问题标题】:I want to count the occurrences of an element in a list我想计算列表中某个元素的出现次数
【发布时间】:2016-05-29 07:58:58
【问题描述】:

我想计算列表中某个元素的出现次数,如果有,则谓词唯一性为真,否则为假。但是,如果元素出现不止一次,Prolog 会发现它是真的。我不知道该怎么办...

count([], X, 0).
count([X|T], X, Y) :- count(T, X, Z), Y is 1+Z, write(Z).
count([_|T], X, Z) :- count(T, X, Z).

unique(St, [Y|RestList]) :- count([Y|RestList], St, N), N =:= 1.

【问题讨论】:

    标签: list count prolog clpfd prolog-dif


    【解决方案1】:

    只要第一个参数是一个基本列表,该解决方案就可以工作。在其他一些情况下,它是不正确的:

    ?- count([E], a, 0).
    false.
    

    我们在这里问

    长度为 1 的列表的元素 E 必须如何看起来才能使列表包含 0 次出现的 a

    事实上,这个问题也有答案,比如E = bE = c

    ?- count([b],a,0).
    true.
    
    ?- count([c],a,0).
    true.
    

    因此,Prolog 的回答是不完整。它应该说,是的。但是怎么做呢?

    count([], _, 0).
    count([E|Es], F, N0) :-
       count(Es, F, N1),
       if_(E = F, D = 1, D = 0),
       N0 is N1+D.
    

    这使用if_/3(=)/3

    ?- length(Xs, I), count_dif(Xs, a, N).
       Xs = [],
       I = N, N = 0
    ;  Xs = [a],
       I = N, N = 1
    ;  Xs = [_A],
       I = 1,
       N = 0,
       dif(_A, a)
    ;  Xs = [a, a],
       I = N, N = 2
    ;  Xs = [_A, a],
       I = 2,
       N = 1,
       dif(_A, a) ;
       Xs = [a, _A],
       I = 2,
       N = 1,
       dif(_A, a) ;
       Xs = [_A, _B],
       I = 2,
       N = 0,
       dif(_A, a),
       dif(_B, a)
    ...
    

    为了进一步改进这一点,我们可能会使用 library(clpfd),因为它在 SICStus、YAP 和 SWI 中可用。

    :- use_module(library(clpfd)).
    
    count([], _, 0).
    count([E|Es], F, N0) :-
       N0 #>= 0,
       if_(E = F, D = 1, D = 0),
       N0 #= N1+D,
       count(Es, F, N1).
    

    现在甚至以下内容也终止了:

    ?- count([a,a|_], a, 1).
    false.
    
    ?- N #< 2, count([a,a|_], a, N).
    false.
    

    【讨论】:

      【解决方案2】:

      使用您自己的子句,我只是对程序进行了一点优化:

      • 用匿名变量替换单例变量
      • 在计数谓词的第二个子句上添加一个删减
      • 删除唯一子句的第二个条件。

      这是现在的程序:

      count([],_,0).
      
      count([X|T],X,Y):- !, count(T,X,Z), Y is 1+Z.
      
      count([_|T],X,Z):- count(T,X,Z).
      
      unique(St,L):- count(L,St,1).
      

      咨询:

      ?- count([2,3,4,3], 3,N).
      N = 2.
      
      ?- unique(3, [2,3,4,5]).
      true.
      

      【讨论】:

      • 哇,效果很好,你是最棒的,非常感谢,我已经为这个练习工作了很多小时,非常感谢!!!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-20
      • 2020-06-09
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      相关资源
      最近更新 更多