有一种方法(嗯,无限的方法)可以使用 prolog 内置函数来解决这个问题,例如 sort/2、findall/3、member/2、include/3 和 length/2:
?- 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],
频率 = [[2, 1], [12, 2], [3, 3], [3, 4], [1, 6]],
SFreqs = [[1, 6], [2, 1], [3, 3], [3, 4], [12, 2]],
频率 = 12,
最常见 = 2,
列表长度 = 21。
根据讲师为解决练习设置的限制,您可能需要自己实现这些内置函数中的一个或多个。
另一种更有效的方法是使用msort/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|...],
RLE = [[2, 1], [12, 2], [3, 3], [3, 4], [1, 6]],
SRLE = [[1, 6], [2, 1], [3, 3], [3, 4], [12, 2]],
频率 = 12,
最常见 = 2,
列表长度 = 21。