我需要在Prolog中的列表列表中找到最大数量,然后“打印”(在新列表中输出)包含该最大数量的列表。
例如:lists_with_max([[1,2,3],[2,3,44],[44,5,6],列表)。 应该输出:列表= [[2,3,44],[44,5,6]]
下面的代码是我能想到的最接近的代码,并且没有错误,但是显然这是错误的,因为每次它找到一个新的max然后输出错误的列表。
'max'查找列表中的最大数目。 “扁平化”“扁平化”列表。 “ maxl”在列表列表中找到最大数目。
max([X], X).
max([H|T], H):-
max(T, MaxT),
H > MaxT.
max([H|T], MaxT):-
max(T, MaxT),
H =< MaxT.
flat([], []).
flat([H|T], [H|LT]):-
atomic(H),
flat(T, LT).
flat([H|T], L):-
flat(T, LT),
not(atomic(H)),
flat(H, LH),
append(LH, LT, L).
maxl(List,Max):-
flat(List,Newlist),
max(Newlist,Max).
lists_with_max([],[]).
lists_with_max([H|T],[H|L]):-
maxl([H|T],Max),
member(Max,H),
lists_with_max(T,L).
lists_with_max([_H|T],L):-
lists_with_max(T,L).
答案 0 :(得分:2)
这是使用构建谓词max_list/2,maplist/3,include/3和memberchk/2的另一种方法:
lists_with_max(LL, LL1):-
maplist(max_list, LL, ML),
max_list(ML, M),
include(memberchk(M), LL, LL1).
答案 1 :(得分:0)
我认为您在maxl/2
和flat/2
的帮助下走了一些路,您实际上并不需要它们来解决您的问题。 IMO并不是一个很好的例子,可以通过对问题进行一堆递归来完成某件事,您实际上将必须仔细查看所有列表,找到max元素,然后再次仔细查看所有列表。不过您的max/2
很好。
所以,我们找到max元素:
setof(Max, L^(member(L, Lists), max(L, Max)), Maxes),
这是一个元谓词,它将遍历所有列表以获取该列表的最大值,并为每个列表的最大值创建一个新列表。我认为良好的Prolog应该具有流利的品质;如果将查询改写为更像逻辑的词,则将出现“列表的最大值是包含每个列表的最大值的列表”之类的内容,最终您将得到类似所看到的内容。 L^
的意思是,我们不希望将其按列表生成的列表L
进行分组(在您作为Prolog程序员的生活中,有时还会有您想要的列表)此分组)。可能使用findall/3
会产生相同的效果,但我更喜欢setof/3
。
接下来,让我们找到最大数:
max(Maxes, Max),
相当简单。现在,让我们查找其中包含最大值的所有列表:
setof(L, (member(L, Lists), member(Max, L)), Result).
这是与第一个相似的另一个,我们说的是“找到所有列表L,以使L在Lists中,而Max在L中”。总而言之,我们拥有:
lists_with_max(Lists, Result) :-
setof(Max, L^(member(L, Lists), max(L, Max)), Maxes),
max(Maxes, Max),
setof(L, (member(L, Lists), member(Max, L)), Result).
另一种做max/2
的方法,我在这里主要是为了向您展示思考Prolog的另一种方法,因为它是这样,效率较低且有点可怕的方法:
max(List, Max) :-
member(Max, List),
\+ (member(Y, List), Y > Max).
这不是很好的样式,但是它确实表明您有时可以告诉Prolog您想要什么而不是如何找到它。这表示List of Max是List Max的成员,因此List的成员Y都不大于它。我希望能得到深思熟虑。