0

I'm trying to write a Prolog function that given a list returns the element(s) that repeats most times in that list, like:

['a', 'a', 'b', 'c', 'b'] should return ['a', 'b'] ['c', 'a', 'a', 'c', 'b', 'c', 'b'] should return ['c'] etc...

I'm trying to do it with another function (that counts the number of times something exists on a list (countlist), but I'm not getting anywhere. A little help please?

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).
false
  • 10,264
  • 13
  • 101
  • 209
Tiago
  • 21
  • 3

2 Answers2

1

How about this:

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)).

Here goes a little explanation of this algorithm:

The idea is to iterate through the list removing the first occurrence of each item which yields a new list. Then, recursively apply the same algorithm to this new list until we get an empty list as a result. At this point we know that the previous list is the list we are looking for.

The second clause of listmax/4 is the iterative clause which checks whether this is the first time that the item is seen. The list of seen items is kept in the second argument of this predicate. The third argument collects the remaining items (the ones which are not seen for the first time).

The first clause of listmax/4 is the base case. It comes into play when we are done iterating through the list. At this point it checks whether the remaining items list is empty, in which case we know that the Seen list is the list we are looking for. Otherwise we apply the algorithm again but using the 'remaining list' as the input list.

gusbro
  • 22,357
  • 35
  • 46
0

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).
尾崎隆大
  • 148
  • 1
  • 1