List 如何在prolog中找到列表的模式?
有人能告诉我如何在Prolog中找到列表的模式吗 我试过这个:List 如何在prolog中找到列表的模式?,list,prolog,mode,List,Prolog,Mode,有人能告诉我如何在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([], _, 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).
它仅返回列表中出现的最大值。但是我需要返回出现次数最多的元素(列表中最频繁的值)。您实际上与
count\u elt/3
非常接近,但是您需要更多的非确定性。简言之,您需要找到一种表达count\u 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
库。因此,首先确定并从那里开始
编辑:一些一般性评论:
- 您可以将
写成[H1 |[H2 | T]]
,这一点更为清楚[H1,H2 | T]
应该返回第二个位置的项目,而不是计数。由于执行此过程需要计数,因此可能需要制作一个listMode/2
或listMode/3
助手来管理递归期间的状态listMode/5
% 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.
值得深思。关于代码,您已经从Daniel那里得到了很好的建议。我将展示一种library()获取信息的替代方法:
mode_of_list(L, M) :-
setof(C-E, (member(E, L), aggregate(count, member(E, L), C)), M).
试验
希望你已经得到了很多建议。这是您的工作代码
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).
反例:
列表([],M)的模式。
应该成功,但您的定义失败<代码>列表的模式([a,X],M)。有两个独立的答案。为什么空列表应该有模式?存在变量时的行为相当复杂。OTOH I将使用带有变量的列表归类为高级…使用/3计数可能是正确和有效的。目前它既不是nor,也不是false。请查看编辑,并让我知道我是否支持您。不!您仍然在创建不必要的选择点。等式具体化的思想是允许索引,只使用一次,然后对结果进行索引。以这种方式,只要术语为=或dif,就没有选择点。只有在两者之间,一个人才会付钱。好吧!仍然缺少的是尾部递归性(但这只是为了完全完美)。谢谢!我必须用累加器arg重写以获得尾部递归性,对吗?
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].
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).