List 如何在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) :-

有人能告诉我如何在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).

它仅返回列表中出现的最大值。但是我需要返回出现次数最多的元素(列表中最频繁的值)。

您实际上与
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已经决定展示解决方案,即使这很可能是家庭作业,我想我还是用@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.

值得深思。

关于代码,您已经从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).