Максимальное количество вхождений в списке
Я пытаюсь написать функцию Prolog, которая с учетом списка возвращает элемент (ы), который повторяется в этом списке чаще всего, например:
['a', 'a', 'b', 'c', 'b'] должны возвращать ['a', 'b'] ['c', 'a', 'a', 'c', 'b', 'c', 'b'] должны возвращать ['c'] и т. д.
Я пытаюсь сделать это с помощью другой функции (которая подсчитывает, сколько раз что-то существует в списке (countlist), но я ничего не получаю. Небольшая помощь, пожалуйста?
listMax(In, Out) :-
listMax(In, Out, 0).
listMax([H | L], [H | O], Max) :-
countlist(H, [H | L], N),
N > Max,
listMax(L, [H | O], N).
listMax([H | L], O, Max) :-
countlist(H, [H | L], N),
<=(Max, N),
listMax(L, O, Max).
listMax([], [], _Max).
listMax([], _O, _Max).
2 ответа
Как насчет этого:
listmax(L, M):-
listmax(L, [], [], M).
listmax([], Seen, MMax, Max):-
MMax=[] -> Max=Seen ; listmax(MMax, [], [], Max).
listmax([H|T], Seen, MMax, Max):-
(member(H, Seen) ->
listmax(T, Seen, [H|MMax], Max) ;
listmax(T, [H|Seen], MMax, Max)).
Вот небольшое объяснение этого алгоритма:
Идея состоит в том, чтобы выполнять итерацию по списку, удаляя первое вхождение каждого элемента, что приводит к созданию нового списка. Затем рекурсивно применяйте тот же алгоритм к этому новому списку, пока в результате мы не получим пустой список. На данный момент мы знаем, что предыдущий список - это список, который мы ищем.
Второе предложение listmax/4 - это итеративное предложение, которое проверяет, является ли это первый раз, когда элемент виден. Список видимых предметов хранится во втором аргументе этого предиката. Третий аргумент собирает оставшиеся элементы (те, которые не видны в первый раз).
Первый пункт listmax/4 является базовым случаем. Он вступает в игру, когда мы закончим список. На этом этапе он проверяет, является ли список оставшихся элементов пустым, и в этом случае мы знаем, что список увиденных - это список, который мы ищем. В противном случае мы снова применяем алгоритм, но в качестве входного списка используем "остающийся список".
listmax(In,Out) :-
setof(A,member(A,In),L1),
findall([Count,A],(
member(A,L1),
count(A,In,Count)),
L2),
max_1(L2,Max),
findall(A,member([Max,A],L2),Out).
count(A,[],0).
count(A,[A|R],X) :-
count(A,R,Y),
X is Y + 1.
count(A,[_|R],X) :-
count(A,R,X).
max_1(L,Max) :-
findall(A,member([A|_],L),L1),
max(L1,Max).