The predicate mostcommonitems_in/2
(to be presented in this answer) bears more than a little resemblance to
mostcommonitem_in/2
, defined in one of my previous answers.
In the following we use list_counts/2
, Prolog lambdas, foldl/4
, tchoose/3
, and (=)/3
:
:- use_module(library(lambda)).
mostcommonitems_in(Ms,Xs) :-
list_counts(Xs,Cs),
foldl(\ (_-N)^M0^M1^(M1 is max(M0,N)),Cs,0,M),
tchoose(\ (E-N)^E^(N=M), Cs,Ms).
Let's run some queries!
First, the three queries given by the OP:
?- mostcommonitems_in(Xs,[1,3,3,4,2,2]).
Xs = [3,2].
?- mostcommonitems_in(Xs,[1,3,3,3,3,4,2,2]).
Xs = [3].
?- mostcommonitems_in(Xs,[1,3,4,2]).
Xs = [1,3,4,2].
Alright! Some more ground queries---hat tip to @lurker and @rpax:
?- mostcommonitems_in(Xs,[1,3,2,1,3,3,1,4,1]).
Xs = [1].
?- mostcommonitems_in(Xs,[1,3,3,4,3,2]).
Xs = [3].
?- mostcommonitems_in(Xs,[1,2,3,4,5,6]).
Xs = [1,2,3,4,5,6].
?- mostcommonitems_in(Xs,[1,3,3,4,2,3,2,2]).
Xs = [3,2].
OK! How about three items each of which occurs exactly three times in the list?
?- mostcommonitems_in(Xs,[a,b,c,a,b,c,a,b,c,x,d,e]).
Xs = [a,b,c]. % works as expected
How about the following somewhat more general query?
?- mostcommonitems_in(Xs,[A,B,C]).
Xs = [C] , A=B , B=C
; Xs = [B] , A=B , dif(B,C)
; Xs = [C] , A=C , dif(B,C)
; Xs = [C] , dif(A,C), B=C
; Xs = [A,B,C], dif(A,B), dif(A,C), dif(B,C).
Above query breaks almost all impure codes... Our Prolog code is pure, so we're good to go!