如果两个元素重复相同的次数,我想找到一种方法来查找列表中最重复的元素。我希望谓词是一个包含两个元素的列表。我怎么能这样做?
示例查询和预期答案:
?- maxRepeated([1,3,3,4,2,2],X).
X = [3,2].
% common case: there is one element that is the most repeated
?- maxRepeated([1,3,3,3,3,4,2,2],X).
X = [3].
% all elements repeat the same number of times
?- maxRepeated([1,3,4,2],X).
X = [1,3,4,2].
我对重复次数较少的元素也有同样的问题。
答案 0 :(得分:2)
谓词mostcommonitems_in/2
(在这个答案中呈现)与...有很多相似之处
mostcommonitem_in/2
,defined in one of my previous answers。
在下文中,我们使用list_counts/2
,Prolog lambdas,foldl/4
,tchoose/3
和(=)/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).
让我们运行一些查询!
首先,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].
好的!一些更多的基础查询 - 给@lurker和@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! 三个项目如何在列表中正好出现三次?
?- mostcommonitems_in(Xs,[a,b,c,a,b,c,a,b,c,x,d,e]).
Xs = [a,b,c]. % works as expected
以下稍微更通用的查询怎么样?
?- 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).
以上查询打破几乎所有不纯的代码...我们的Prolog代码是纯,所以我们很高兴去!
答案 1 :(得分:0)
我不太了解prolog,可能还有更好的方法,但这是一个有效的解决方案:(SWI prolog)
%List of tuples, keeps track of the number of repetitions.
modify([],X,[(X,1)]).
modify([(X,Y)|Xs],X,[(X,K)|Xs]):- K is Y+1.
modify([(Z,Y)|Xs],X,[(Z,Y)|K]):- Z =\= X, modify(Xs,X,K).
highest((X1,Y1),(_,Y2),(X1,Y1)):- Y1 >= Y2.
highest((_,Y1),(X2,Y2),(X2,Y2)):- Y2 > Y1.
maxR([X],X).
maxR([X|Xs],K):- maxR(Xs,Z),highest(X,Z,K).
rep([],R,R).
rep([X|Xs],R,R1):-modify(R,X,R2),rep(Xs,R2,R1).
maxRepeated(X,R):- rep(X,[],K),maxR(K,R).
?- maxRepeated([1,3,3,4,3,2] ,X).
X = (3, 3) .
?- maxRepeated([1,2,3,4,5,6] ,X).
X = (1, 1) .
重复性较低的元素是类似的。
我认为在这种情况下使用元组会更好,但将结果更改为列表应该不是问题。
答案 2 :(得分:-3)
Visual Prolog上有我的解决方案:
domains
value=integer
tuple=t(value,integer)
list=value*
tuples=tuple*
predicates
modify(tuples,value,tuples)
highest(tuple,tuple,tuple)
maxR(tuples,integer,integer)
maxR(tuples,integer)
rep(list,tuples,tuples)
maxRepeated(list,list)
filter(tuples,integer,list)
clauses
modify([],X,[t(X,1)]):- !.
modify([t(X,Y)|Xs],X,[t(X,K)|Xs]):- K = Y+1, !.
modify([t(Z,Y)|Xs],X,[t(Z,Y)|K]):- Z <> X, modify(Xs,X,K).
highest(t(X1,Y1),t(_,Y2),t(X1,Y1)):- Y1 >= Y2, !.
highest(t(_,Y1),t(X2,Y2),t(X2,Y2)):- Y2 > Y1.
maxR([],R,R):- !.
maxR([t(_,K)|Xs],Rs,R):- K>Rs,!, maxR(Xs,K,R).
maxR([_|Xs],Rs,R):- maxR(Xs,Rs,R).
maxR(X,R):- maxR(X,0,R).
rep([],R,R).
rep([X|Xs],R,R1):-modify(R,X,R2),rep(Xs,R2,R1).
filter([],_,[]):-!.
filter([t(X,K)|Xs],K,[X|FXs]):- !, filter(Xs,K,FXs).
filter([_|Xs],K,FXs):- filter(Xs,K,FXs).
maxRepeated(X,RL):- rep(X,[],Reps),maxR(Reps,K),filter(Reps,K,RL).
goal
maxRepeated([1,3,3,4,2,3,2,2] ,X),
maxRepeated([1,2,3,4,5,6] ,Y).