5

我刚刚被介绍给 Prolog,并且正在尝试编写一个谓词来查找整数列表的最大值。我需要写一个从头开始比较,另一个从结尾比较。到目前为止,我有:

max2([],R).
max2([X|Xs], R):- X > R, max2(Xs, X).
max2([X|Xs], R):- X <= R, max2(Xs, R).

我意识到 R 尚未启动,因此无法进行比较。我需要 3 个参数来完成这个吗?

4

10 回答 10

5
my_max([], R, R). %end
my_max([X|Xs], WK, R):- X >  WK, my_max(Xs, X, R). %WK is Carry about
my_max([X|Xs], WK, R):- X =< WK, my_max(Xs, WK, R).
my_max([X|Xs], R):- my_max(Xs, X, R). %start

另一种方式

%max of list
max_l([X],X) :- !, true.
%max_l([X],X). %unuse cut
%max_l([X],X):- false.
max_l([X|Xs], M):- max_l(Xs, M), M >= X.
max_l([X|Xs], X):- max_l(Xs, M), X >  M.
于 2013-11-05T21:46:14.027 回答
5

忽略关于从开头或结尾开始的作业约束,实现获得数值最大值的谓词的正确方法如下:

list_max([P|T], O) :- list_max(T, P, O).

list_max([], P, P).
list_max([H|T], P, O) :-
    (    H > P
    ->   list_max(T, H, O)
    ;    list_max(T, P, O)).
于 2013-11-06T11:09:17.530 回答
4

作为 BLUEPIXY 答案的替代方案,SWI-Prolog 有一个内置谓词 ,max_list/2它会为您进行搜索。您还可以考虑一种较慢的方法,IMO 有助于熟悉更多内置函数和不确定性(然后回溯):

slow_max(L, Max) :-
   select(Max, L, Rest), \+ (member(E, Rest), E > Max).

产量

2 ?- slow_max([1,2,3,4,5,6,10,7,8],X).
X = 10 ;
false.

3 ?- slow_max([1,2,10,3,4,5,6,10,7,8],X).
X = 10 ;
X = 10 ;
false.

编辑

请注意,您并不严格需要三个参数,而只是需要正确实例化变量来进行比较。然后您可以“反转”值流:

max2([R], R).
max2([X|Xs], R):- max2(Xs, T), (X > T -> R = X ; R = T).

同样,这比其他答案中建议的三个参数循环慢,因为它会破坏“尾递归优化”。此外,它确实只是找到最大值之一

2 ?- max2([1,2,3,10,5,10,6],X).
X = 10 ;
false.
于 2013-11-05T22:20:12.163 回答
4

以下是使用lambda 表达式 foldl/4以及可选的clpfd 的方法

:- use_module([library(lambda),library(apply),library(clpfd)]).

numbers_max([Z|Zs],Max) :- foldl(\X^S^M^(M is max(X,S)),Zs,Z,Max).
fdvars_max( [Z|Zs],Max) :- foldl(\X^S^M^(M #= max(X,S)),Zs,Z,Max).

让我们运行一些查询!

?- numbers_max([1, 4 ,2,3],M)。% 整数:都是不同的
M = 4。% 确定性地成功
?- fdvars_max( [1, 4 ,2,3],M)。
M = 4。% 确定性地成功

?- numbers_max([1, 4 ,2,3, 4 ],M)。% 整数:M 出现两次
M = 4。% 确定性地成功
?- fdvars_max( [1, 4 ,2,3, 4 ],M)。
M = 4。% 确定性地成功

如果列表为空怎么办?

?- numbers_max([],M).
false.
?- fdvars_max( [],M).
false.

numbers_max/2最后,一些查询显示和 之间的差异fdvars_max/2

?- numbers_max([1,2,3, 10.0 ],M)。% 整数 + 浮点数
M = 10.0。
?- fdvars_max( [1,2,3, 10.0 ],M)。% 整数 + 浮点数
错误:域错误:预期为“clpfd_expression”,发现为“10.0”

?- numbers_max([ A , B , C ],M)。% 更多的一般用途  
错误:is/2:参数没有充分实例化
?- fdvars_max( [ A , B , C ],M)。
M#>=_X, M#>= C , M#=max( C ,_X), _X#>= A , _X#>= B , _X#=max( B , A )。剩余目标百分比
于 2015-05-18T11:55:17.767 回答
3

一个非常简单的方法(从头开始)如下:

maxlist([],0).

maxlist([Head|Tail],Max) :-
    maxlist(Tail,TailMax),
    Head > TailMax,
    Max is Head.

maxlist([Head|Tail],Max) :-
    maxlist(Tail,TailMax),
    Head =< TailMax,
    Max is TailMax.

如您所说,如果要计算算术表达式,则必须实例化变量。要解决这个问题,首先你必须进行递归调用,然后进行比较。

希望能帮助到你!

于 2016-12-22T11:35:13.387 回答
1

现在我正在使用 Prolog 中的递归,所以如果它对某人有用,我会留下“我的两分钱”以我认为的两种方式解决它:

% Start
start :- max_trad([2, 4, 6, 0, 5], MaxNumber1),
         max_tail([2, 4, 6, 0, 5], 0, MaxNumber2),
         show_results(MaxNumber1, MaxNumber2).

% Traditional Recursion (Method 1)
max_trad([Head|Tail], Max) :- max_trad(Tail, Value), Head > Value, Max is Head.
max_trad([Head|Tail], Max) :- max_trad(Tail, Value), Head =< Value, Max is Value.
max_trad([], 0).

% Tail Recursion (Method 2)
max_tail([], PartialMax, PartialMax).
max_tail([Head|Tail], PartialMax, FinalMax) :- Head > PartialMax, max_tail(Tail, Head, FinalMax).
max_tail([_|Tail], PartialMax, FinalMax) :- max_tail(Tail, PartialMax, FinalMax).

% Show both of the results
show_results(MaxNumber1, MaxNumber2) :-
    write("The max value (obtained with traditional recursion) is: "), writeln(MaxNumber1),
    write("The max value (obtained with tail recursion) is: "), writeln(MaxNumber2).

上述代码的输出是:

在此处输入图像描述

两种方法相似,不同之处在于第二种方法在递归中使用了一个辅助变量来向前传递值,而在第一种方法中,虽然我们少了一个变量,但我们正在用稍后执行的指令填充堆栈,因此,如果它是一个夸大的列表,则第二种方法是合适的。

于 2021-06-21T04:41:38.590 回答
1
list_max([L|Ls], Max) :- foldl(num_num_max, Ls, L, Max).

num_num_max(X, Y, Max) :- Max is max(X, Y).

%Query will be

?-list_max([4,12,5,3,8,90,10,11],Max).
Max=90
于 2017-04-16T21:26:05.457 回答
0
 maximum_no([],Max):-

    write("Maximum No From the List is:: ",Max).
maximum_no([H|T],Max):-
    H>Max,
    N = H,
    maximum_no(T,N).
maximum_no(L,Max):-
    maximum_no(L,Max).
于 2017-04-26T09:43:27.993 回答
0

Prolog 列表中的最大数量?

max([],A):-print(A),!.

max([Head | Tail] , A):-A =< Head ,A1 is Head , max(Tail,A1) ; max(Tail,A).
于 2020-01-31T13:57:08.263 回答
-2

最大(L,M):-成员(M,L),findall(X,(成员(X,L),X>M),NL),长度(NL,0)。

于 2019-07-25T17:53:33.917 回答