Prolog:返回列表中最常用元素的函数

时间:2018-05-20 17:33:00

标签: list prolog

我有一个赋值,它需要一个返回(如果存在)一个元素的函数,该元素显示在列表的一半以上,否则返回no。所以我已经创建了一个函数来查找列表的长度,但现在我需要一个方法来

找到最具递归元素及其在列表中找到的时间

有什么想法吗?我是Prolog的新手,我要求我的任务,所以如果有人要帮助我,只是给我提示或启发我,我不想要任何实际的代码来复制粘贴。

3 个答案:

答案 0 :(得分:1)

图书馆(aggregate)值得学习......

?- L=[1,2,3,3,3,1,2,3],aggregate(max(C,E),aggregate(count,member(E,L),C),R).
L = [1, 2, 3, 3, 3, 1, 2, 3],
R = max(4, 3).

编辑:考虑有关列表长度的出现的要求:

?- L=[3,2,6,2,4],length(L,Len),HalfLen is Len/2, aggregate(max(C,E),(aggregate(count,member(E,L),C),C>HalfLen),R).
false.

答案 1 :(得分:0)

有一种方法(好的,无限的方式)可以使用prolog内置来解决这个问题,例如sort/2findall/3member/2include/3和{{3} }:

?- List=[3,2,6,2,2,1,4,2,2,2,2,4,1,2,3,2,2,4,2,3,2],
    sort(List, Uniq),                 % sort removing duplicate elements
    findall([Freq, X], (
        member(X, Uniq),              % for each unique element X
        include(=(X), List, XX),      %
        length(XX, Freq)              % count how many times appears in List
    ), Freqs),
    sort(Freqs, SFreqs),              % sort (by frequency)
    last(SFreqs, [Freq, MostCommon]), % last pair is the most common
    length(List, ListLen),
    Freq > ListLen/2.                 % is frequency greater than half list length?
  

列表= [3,2,6,2,2,1,4,2,2 | ...],

     

Uniq = [1,2,3,4,6],

     

Freqs = [[2,1],[12,2],[3,3],[3,4],[1,6]],

     

SFreqs = [[1,6],[2,1],[3,3],[3,4],[12,2]],

     

Freq = 12,

     

MostCommon = 2,

     

ListLen = 21。

根据教师为解决练习所做的限制,您可能需要自己实施一个或多个内置。

另一种更有效的方法是使用length/2,然后创建排序列表的行程编码,然后再次对其进行排序,并选择代表最常出现元素的元素。现在我无法在不定义辅助递归谓词的情况下弄清楚如何进行行程编码,所以这里是:

count_repeated([Elem|Xs], Elem, Count, Ys) :-
    count_repeated(Xs, Elem, Count1, Ys), Count is Count1+1.
count_repeated([AnotherElem|Ys], Elem, 0, [AnotherElem|Ys]) :-
    Elem \= AnotherElem.
count_repeated([], _, 0, []).

rle([X|Xs], [[C,X]|Ys]) :-
    count_repeated([X|Xs], X, C, Zs),
    rle(Zs, Ys).
rle([], []).

然后,获得最常见的元素可以通过以下方式完成:

?- List=[3,2,6,2,2,1,4,2,2,2,2,4,1,2,3,2,2,4,2,3,2],
    msort(List, SList),
    rle(SList, RLE),
    sort(RLE, SRLE),
    last(SRLE, [Freq, MostCommon]),
    length(List, ListLen),
    Freq > ListLen/2.
  

列表= [3,2,6,2,2,1,4,2,2 | ...],

     

SList = [1,1,2,2,2,2,2,2 2,2 | ...],

     

RLE = [[2,1],[12,2],[3,3],[3,4],[1,6]],

     

SRLE = [[1,6],[2,1],[3,3],[3,4],[12,2]],

     

Freq = 12,

     

MostCommon = 2,

     

ListLen = 21。

答案 2 :(得分:0)

foldl可能是你的朋友:

:- use_module(library(lambda)).
count_repeat(L, R, N) :-
    foldl(\X^Y^Z^(select(V-X, Y, Y1)-> V1 is V+1, Z = [V1-X|Y1]; Z = [1-X|Y]), L, [], L1),
    sort(L1,L2),
    last(L2, N-R).

结果:

  

? - count_repeat([3,2,6,2,4,1,4,2,5,3,2,4,1,2,3,1,2,4,5,3,2] ,R,N)。

     

R = 2,

     

N = 7。