有人可以告诉我如何在Prolog中找到列表模式吗?
我试过这个:
count_elt([], _, 0) :- !.
count_elt([H|T], H, P) :-
count_elt(T, H, P1),
P is P1 + 1, !.
count_elt([_|T], E, P) :- count_elt(T, E, P).
listMode([], 0) :- !.
listMode([_], 1) :- !.
listMode([H1|[H2|T]], M) :-
count_elt([H1|[H2|T]], H1, C),
listMode([H2|T], C1),
C > C1,
M is C, !.
listMode([_|[H2|T]], M) :- listMode([H2|T], M).
仅返回列表中的最大值。但我需要返回具有最大值的元素(列表中最常见的值)。
答案 0 :(得分:3)
你实际上与count_elt/3
非常接近,但你需要更多的非决定论。简而言之,您需要找到一种方法来表达count_elt/3
更少的削减,因为现在你得到这个:
?- count_elt([a,b,a,a,c,b,d,e,a,f], Y, X).
Y = a,
X = 4.
你想要得到的是:
?- count_elt([a,b,a,a,c,b,d,e,a,f], Y, X).
Y = a,
X = 4 ;
Y = b,
X = 2 ;
Y = c,
X = 1 ;
...
Y = f,
X = 1 ;
false.
从那里你只是试图找到具有最大值的解决方案,你可以使用setof/3
或逻辑表达式或使用aggregate
库。因此,首先修复count_elt/3
并从那里开始。
修改:一些一般性评论:
[H1|[H2|T]]
写为[H1,H2|T]
,这有点清晰。listMode/2
可能应该在第二个位置返回项目而不是计数。由于您需要计数来执行此过程,因此您可能需要在递归期间创建listMode/3
或listMode/5
帮助程序来管理您的状态。修改:解决方案
由于@MaDu_LK决定展示解决方案,即使这很可能是家庭作业,我想我会分享我的,使用@ false's reified equality predicate:
count_of([], _, 0).
count_of([H|Rest], E, N1) :-
equality_reified(H, E, Bool),
count_of(Rest, E, N0),
(Bool == true -> N1 is N0 + 1 ; N1 = N0).
frequency(L, I, N) :-
sort(L, LSorted),
member(I, LSorted),
count_of(L, I, N).
mode(L, X) :-
frequency(L, X, NMax),
\+ (frequency(L, _, NBigger),
NMax < NBigger).
这有一些更令人愉悦的性能属性:
% MaDu_LK
?- time(get_mode([a,b,c,a,b,c,a,a,b,c,a,d,b], X)).
% 2,811 inferences, 0.000 CPU in 0.000 seconds (100% CPU, 7117429 Lips)
X = a.
% mine
?- time(mode([a,b,c,a,b,c,a,a,b,c,a,d,b], X)).
% 217 inferences, 0.000 CPU in 0.000 seconds (98% CPU, 3144928 Lips)
X = a ;
% 195 inferences, 0.000 CPU in 0.000 seconds (97% CPU, 3305085 Lips)
false.
另一种解决方案也只生成一种模式,即使列表是多模式的:
% MaDu_LK
?- get_mode([a,a,b,b,c], X).
X = a.
% mine
?- mode([a,a,b,b,c], X).
X = a ;
X = b ;
false.
深思熟虑。
答案 1 :(得分:1)
你已经从Daniel得到了关于你的代码的好建议。我将展示一个库(aggregate)替代方法来获取信息:
mode_of_list(L, M) :-
setof(C-E, (member(E, L), aggregate(count, member(E, L), C)), M).
测试
?- mode_of_list([a,b,a,a,c,b,d,e,a,f],L).
L = [1-c, 1-d, 1-e, 1-f, 2-b, 4-a].
答案 2 :(得分:-1)
希望你已经得到了很多建议。这是适合你的代码。
count_elt([],_,0):-!.
count_elt([H|T],H,C):-count_elt(T,H,C1),C is C1+1,!.
count_elt([_|T],E,C):-count_elt(T,E,C).
listMode([],0) :- !.
listMode([_],1) :- !.
listMode([H1|[H2|T]], M) :-count_elt([H1|[H2|T]],H1,C),listMode([H2|T],C1),C > C1,M is C,!.
listMode([_|[H2|T]],M) :- listMode([H2|T],M).
get_mode([H|T],M):-listMode([H|T],K),count_elt([H|T],M,K).