如何查找和输出列表(包括所有列表的最大数量)?序言

时间:2019-06-06 16:35:16

标签: list prolog

我需要在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).

2 个答案:

答案 0 :(得分:2)

这是使用构建谓词max_list/2maplist/3include/3memberchk/2的另一种方法:

lists_with_max(LL, LL1):-
  maplist(max_list, LL, ML),
  max_list(ML, M),
  include(memberchk(M), LL, LL1).

答案 1 :(得分:0)

我认为您在maxl/2flat/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都不大于它。我希望能得到深思熟虑。