查找列表Swi-prolog的最大和最小元素之和

时间:2018-04-15 20:06:06

标签: prolog

请帮忙,我是Prolog的新手试图查找列表的最大和最小元素的总和,但这段代码不起作用。

max([H|[]], Max) :- Max is H,!.
max([H|T], Max) :-
    max(T, Max1),
    Max1 > H,
    Max is Max1, !.
max([H|T], Max) :-
    max(T, Max1),
    Max1 < Head,
    Max is Head, !.

minlist([Head|[]], Min) :-
    Min is Head, !.
minlist([Head|List], Min) :-
    minlist(List, Min1),
    Min1 < Head,
    Min is Min1, !.
minlist([Head|List], Min) :-
    max(List, Min1),
    Min1 > Head,
    Min is Head, !.

sum([H|T],S) :-
    S is minlist([H|T],Min) + max([H|T],Max),
    !.

1 个答案:

答案 0 :(得分:1)

每个谓词子句定义末尾的剪切是不必要的。削减的目的是有意识地将不需要但有效的解决方案修改为解决方案搜索。

在Prolog中,算术函数谓词之间存在差异。 算术函数返回一个值(与其他语言中的函数一样),仅用于评估算术表达式的运算符(例如is/2>/2,{{1}等等)。 SWI Prolog不允许您定义自己的算术函数。

谓词是您查询的术语。它们不像函数那样返回值。它们只是成功或失败,并将根据需要在参数中实例化变量以建立成功。此外,在查询中,Prolog将找到尽可能多的变量实例,以便成功,从而可能产生多个解决方案。切割旨在在需要时修剪该过程。在Prolog中,您可以定义自己的谓词。

差异的一个简单示例是至少两个值的谓词:

=:=/2

您可以查询此内容以获得结果:

min(A, B, A) :- A < B.
min(A, B, B) :- A >= B.

Prolog有?- min(4, 2, M). M = 2. 算术函数将按如下方式使用:

min/2

对于代码,您已为列表中的最大值定义了谓词。这是你的谓词,但是为了处理以下问题而重写:

  • 您正在使用?- M is min(4, 2). M = 2. 作为分配运营商,但并非如此。您希望统一可以直接使用参数(如下所示)或使用is/2完成。
  • 你有一个拼写错误:当你的意思是=/2时使用Head
  • 重命名为H以表明其适用于列表

重写以避免削减和不必要地使用max_list来执行&#34;分配&#34;:

is/2

我们实际上可以比这更好一点,因为你的第二和第三个句子max([H], H). % The max of list [H] is H max([H|T], Max) :- max(T, Max), Max > H. max([H|T], H) :- max(T, Max1), Max1 < H. 与第一个子句匹配查询min([H|T], ...)。这将导致可以避免的不必要的匹配。您可以通过确保第2和第3个子句中的列表至少包含两个元素来处理此问题:

min([H], ...)

此实现的另一个问题是,您将根据max_list([H], H). % The max of list [H] is H max_list([X,Y|T], Max) :- max([Y|T], Max), Max > X. max_list([X,Y|T], H) :- max([Y|T], Max1), Max1 < X. 成功还是失败来冗余调用max/2。更多&#34;教科书&#34; Max > X的实现,它避免了这个问题并且是尾递归的,它将是:

max_list

您可以类似地定义max_list([X|Xs], M) :- max_list(Xs, X, M). max_list([], M, M). max_list([X|Xs], Xm, M) :- X > Xm, max_list(Xs, X, M). max_list([X|Xs], Xm, M) :- X =< Xm, max_list(Xs, Xm, M).

然后min_list/2将被写为:

sum/2