【问题标题】:How to find max element in nested list in Prolog?如何在 Prolog 的嵌套列表中找到最大元素?
【发布时间】:2021-03-15 16:40:13
【问题描述】:

我试图在 Prolog 中找到多层列表中的最大元素(意思是列表中的列表...)。问题是,我一一审查了所有谓词,它们都有效,除了那个实际上应该解决我的问题的谓词。我的方法是展平列表(使其成为单层)并在该列表中找到最大元素。这是我的代码:

is_list([]).

add([],L,L).
add([X|L1],L2,[X|L3]):-add(L1,L2,L3).

maximum([X|O],M) :- max(O,X,M),!.
max([X|O],Y,M) :- X=<Y, max(O,Y,M).
max([X|O],Y,M) :- X>Y, max(O,X,M).
max([],M,M).

flatten([],[]).
flatten([X|L1],[X|L2]):-not(is_list(X)),!,flatten(L1,L2).
flatten([X|L1],L2):-flatten(X,LX),flatten(L1,LL1),add(LX,LL1,L2).

maximum_in_multilayered_list(L,M):-flatten(L,L1),maximum(L1,N), M is N.

由于某种原因,我收到以下错误:

?- maximum_in_multilayered_list([1,[2,3],4],X).
ERROR: Type error: `[]' expected, found `[2,3]' (a list) ("x" must hold one character)
ERROR: In:
ERROR:   [13] [2,3]=<1
ERROR:   [12] max([[2|...],4],1,_7284) at c:/users/ace_m/documents/prolog/bp.pl:47
ERROR:   [11] maximum([1,...|...],_7328) at c:/users/ace_m/documents/prolog/bp.pl:46
ERROR:   [10] maximum_in_multilayered_list([1,...|...],_7366) at c:/users/ace_m/documents/prolog/bp.pl:75
ERROR:    [9] <user>
   Exception: (12) max([[2, 3], 4], 1, _7596) ? creep

我知道问题在于我实际上是在将整数列表与整数进行比较,这意味着它们是不兼容的类型,但为什么会这样呢?我做错了什么?

【问题讨论】:

  • 先看flatten([1,[2,3],4],L)。
  • 为什么开头只有一个is_list([]).?不为空的列表怎么办?
  • ^^,此外,is_list/1 是一个内置功能,可以完全按照您的要求完成。没有你的定义,它就可以工作。旁注:add/3 更好地称为append/3,它也是一个内置的。 :)
  • 而且......你不需要展平!只需遍历树寻找最大值(我认为这称为树上的“折叠”操作,而不是列表上的折叠操作)
  • @DavidTonhofer 我已经在我的答案中添加了一个基于聚合的代码,我相信它就是这样做的。

标签: list prolog nested-lists swi-prolog flatten


【解决方案1】:

删除您的is_list([]) 即可。

事实上,任何非空列表都不会被视为is_list/1 材料,因此对于[1,[2,3],4] 中的[2,3],flatten/2 定义中的 second 子句适用,并且将X = [2,3] 按原样 添加到“扁平化”列表[X|L2]。

但is_list/1 已经是一个内置谓词,它完全符合您的要求。


另一种实现方式是使用library(aggregate)。

首先我们定义一个可回溯的谓词,它通过嵌套列表枚举所有非列表(即“普通值”)(取自this我最近的一些相关答案):

nembr(Z, A) :-    % member in nested lists
  is_list(A), member(B,A), nembr(Z,B)
  ;
  \+ is_list(A), A=Z.

然后

18 ?- nembr(X, [1,[2,3],4]).
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
false.

19 ?- use_module(library(aggregate)).
true

20 ?- L = [1,[2,3],4], aggregate( max(X), nembr(X,L), R).
L = [1, [2, 3], 4],
R = 4.

【讨论】:

  • Prolog 就像 Perl:There is more than one way to do it(尽管在你找到失败之前,你可能真的会被失败所困扰,如果你策划了单元测试,编码再次成为一门可靠的实验科学)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-24
  • 2017-01-31
  • 2012-12-29
  • 1970-01-01
  • 2016-07-18
相关资源
最近更新 更多