List 如何在Prolog的嵌套列表中查找max元素?

List 如何在Prolog的嵌套列表中查找max元素?,list,prolog,nested-lists,swi-prolog,flatten,List,Prolog,Nested Lists,Swi Prolog,Flatten,我试图在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

我试图在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.
是一个列表([])。
添加([],L,L)。
添加([X|L1],L2[X|L3]):-add(L1,L2,L3)。
最大值([X | O],M):-max(O,X,M),!。
最大值([X | O],Y,M):-X=Y,最大值(O,X,M)。
最大值([],米,米)。
展平([],[])。
展平([X | L1],[X | L2]):-不(是列表(X)),!,展平(L1,L2)。
展平([X | L1],L2):-展平(X,LX),展平(L1,LL1),添加(LX,LL1,L2)。
多层列表中的最大值(L,M):-展平(L,L1),最大值(L1,N),M是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
?-多层列表中的最大值([1,[2,3],4],X)。
错误:类型错误:应为“[]”,找到“[2,3]”(列表)(“x”必须包含一个字符)
错误:在:
错误:[13][2,3]=删除您的
is\u列表([])
,它就可以工作了

事实上,任何非空列表都不被视为
是列表/1
材料,因此对于
[1,[2,3],4]
中的
[2,3]
而言,
展平/2
定义中的第二条适用,并将
X=[2,3]
原样添加到“展平”列表
[X | L2]

但是,
is_list/1
已经是一个内置谓词,它可以完全满足您的需要


另一种实现方法是使用

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

nembr(Z,A):-%嵌套列表中的成员
is_列表(A),成员(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;
错。
19?-使用_模块(库(聚合))。
真的
20?-L=[1,[2,3],4],骨料(最大值(X),nembr(X,L),R)。
L=[1,2,3,4],
R=4。

首先查看
扁平化([1,2,3,4],L)
为什么一开始就有一个单独的
列表([])。
?那些不是空的列表呢?^^^,此外,
是一个内置的列表/1
可以完成您希望它完成的任务。没有你的定义,它只是工作。旁注:
add/3
更好地称为
append/3
,它也是一个内置的。:)而且。。。你不需要压扁!只需在树上走一走,寻找最大值(我认为这是树上的“折叠”操作,而不是列表上的折叠操作)@DavidTonhofer我在我的答案中添加了一个基于聚合的代码,我相信它就是这样做的(尽管在你找到失败之前,你可能会被失败困扰,如果你策划单元测试,编码再次成为一门坚实的实验科学)