我刚刚接触 Prolog,正在尝试编写一个谓词来查找整数列表的最大值。我需要写一个从头开始比较的内容,另一个从最后开始比较的内容。到目前为止,我已经:
max2([],R).
max2([X|Xs], R):- X > R, max2(Xs, X).
max2([X|Xs], R):- X <= R, max2(Xs, R).
我发现R还没有启动,所以无法进行比较。我需要 3 个参数才能完成这个吗?
忽略从开头或结尾开始的家庭作业约束,实现获取数字最大值的谓词的正确方法如下:
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)).
一个非常简单的方法(从头开始)如下:
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.
正如您所说,如果要计算算术表达式,则必须实例化变量。要解决这个问题,首先必须进行递归调用,然后进行比较。
希望有帮助!
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.
作为 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.
以下是如何使用 lambda 表达式 和 meta-predicate
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)。 % 剩余目标
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
现在我正在 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).
上述代码的输出为:
两种方法类似,不同之处在于第二种方法在递归中使用了辅助变量来向前传递值,而在第一种方法中,虽然我们少了一个变量,但我们用稍后要执行的指令填充堆栈,所以如果是一个过大的列表,第二种方法是合适的。
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).
Prolog 中列表中的最大数量?
max([],A):-print(A),!.
max([Head | Tail] , A):-A =< Head ,A1 is Head , max(Tail,A1) ; max(Tail,A).
对我来说,这是在序言列表中获取最大值和最小值的最简单方法。
% recursively find the max or min of the Tail and compare it with
% the head to get the max or min
max([H | []], H).
max([H | T], Max):- max(T, Max1), Max1 > H, Max is Max1; Max is H.
min([H | []], H).
min([H | T], Min):- min(T, Min1), Min1 < H, Min is Min1; Min is H.
输出:
?- max([1, 5, 3], A).
A = 5 .
?- min([1, 5, 3], A).
A = 1 .
?- min([1, 0, 3], A).
A = 0 .
?- min([], A).
false.
最大(长,中):- 会员(男,L), findall(X,(成员(X,L),X>M),NL), 长度(NL,0).