【问题标题】:Prolog: Incrementing counter depending on elements in a list of listsProlog:根据列表列表中的元素递增计数器
【发布时间】:2014-12-09 04:01:02
【问题描述】:

我正在尝试增加 4 个计数器,具体取决于列表列表中是否包含某个元素。例如,给定:

check_occurences(A,B,C,D,List)

和:

  List = [[a,b,c],[a,b,c,d],[b,d],[a]]

我应该得到:

A = 3; B = 3; C = 2; D = 2

到目前为止我的尝试:

check_occurences(A,B,C,D,List) :- 
   helper(List,a,A), 
   helper(List,b,B), 
   helper(List,c,C), 
   helper(List,d,D).

helper([],_,A).
helper([H|T],Elt,X) :- member(Elt,H), Count = X + 1, helper(T,Elt,Count).
helper([H|T],Elt,X) :- helper(T,Elt,X).

我的代码背后的想法是我为每个计数器调用 helper。如果 Elt 是 X 的成员,我会增加计数器。如果不是,我使用第三个事实继续递归。当列表为空时,我停止。但是,问题在于递增计数器。

编辑:修正了代码中的错误。

【问题讨论】:

  • 使用select 而不是member
  • 不知道你为什么这么建议。我只需要检查一个元素是否是列表的一部分。如果是,我会增加计数器。如果没有,则不要增加。然后我会转到列表中的下一个列表。
  • 哦,对不起,我以为你想数双打。 (这样[a,a,b] 会被计算两次)。

标签: list recursion prolog counter


【解决方案1】:

稍微概括您描述的问题:对于您想知道的给定列表:

  1. 这些列表中有哪些元素。
  2. 对于 (1) 中的每个元素,它出现一次或多次的列表数。

使用一些库,我想出了以下程序:

:- use_module(library(apply)).
:- use_module(library(lists)).
:- use_module(library(pairs)).

check_occurrences(Ls1, Ps3):-
  maplist(sort, Ls1, Ls2),
  append(Ls2, L),
  map_list_to_pairs(count(L), L, Ps1),
  sort(Ps1, Ps2),
  transpose_pairs(Ps2, Ps3).
count(L, X, N):-
  aggregate(count, member(X, L), N).

使用示例:

?- check_occurrences([[a,a,b,c],[a,b,c,d,e,f,g],[b,d,f,g],[a]], Counts).
Counts = [a-3, b-3, c-2, d-2, e-1, f-2, g-2].

【讨论】:

    【解决方案2】:

    如果是我,我可能会首先编写一个通用谓词来计算列表项的频率,如下所示:

    frequencies( []     , Fs, Fs ) .    % once the source list is exhausted, the frequency table is complete
    frequencies( [X|Xs] , Ts, Fs ) :-   % otherwise...
      increment(X,Ts,T1) ,              % - increment the frequency count for X
      frequencies(Xs,T1,Fs)             % - and recurse down.
      .                                 %
    
    increment( X , Ts , Fs ) :-         % to increment the frequency list
      append( Pfx , [X:C|Sfx] , Ts ) ,  % - If X is already a key in the list
      !,                                % - cut off alternatives
      C1 is C+1 ,                       % - increment the count
      append( Pfx , [X:C1|Sfx] , T1 )   % - put the list back together to create the new list.
      .                                 % otherwise...
    increment( X , Fs , [X:1|Fs] ).     % X is not in the list: add it.
    

    那么您的 check_occurences/3 谓词是简单且声明性的:

    check_occurences(A,B,C,D,Xs) :- % to compute a frequency table,
      frequencies( Xs , [], Fs ) ,  % - invoke the helper to compute the frequency table
      frequency_of(a,Fs,A) ,        % - get the count for a
      frequency_of(b,Fs,B) ,        % - get the count for b
      frequency_of(c,Fs,C) ,        % - get the count for c
      frequency_of(d,Fs,D)          % - get the count for d
      .                             % Easy!
    
    frequency_of( _ , []       , 0 ) .    % if the item is not a key in the list, the count is zero.
      frequency_of( X , [X:N|_]  , N ) :- % if the item is a key in the list, succeeed
      .                                   % 
    frequency_of( X , [Y:_|Fs] , N ) :-   % otherwise....
      X \= Y ,                            % - assuming we haven't yet found the desired key
      frequency_of(X,Fs,N)                % - we recurse down
      .                                   %
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-17
      • 1970-01-01
      • 2016-07-18
      相关资源
      最近更新 更多