【问题标题】:Finding the max in a list - Prolog在列表中查找最大值 - Prolog
【发布时间】:2013-11-16 21:48:32
【问题描述】:

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

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

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

【问题讨论】:

标签: prolog


【解决方案1】:
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.

【讨论】:

  • max2([],R). first query :-max2([],R) match max2([],R) 但是无法确定R
  • 谢谢。这会被认为是从头比较还是从头比较?换一种方式你会怎么做?
  • @user2796815 我会这样从头比较。
【解决方案2】:

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

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)).

【讨论】:

    【解决方案3】:

    作为 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.
    

    【讨论】:

      【解决方案4】:

      以下是使用lambda expressions 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/2fdvars_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)。剩余目标百分比

      【讨论】:

        【解决方案5】:

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

        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.
        

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

        希望对你有帮助!

        【讨论】:

          【解决方案6】:
          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
          

          【讨论】:

            【解决方案7】:

            现在我正在使用 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).
            
            

            以上代码的输出为:

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

            【讨论】:

              【解决方案8】:
               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).
              

              【讨论】:

                【解决方案9】:

                Prolog 列表中的最大数量?

                max([],A):-print(A),!.
                
                max([Head | Tail] , A):-A =< Head ,A1 is Head , max(Tail,A1) ; max(Tail,A).
                

                【讨论】:

                  【解决方案10】:

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

                  【讨论】:

                    猜你喜欢
                    • 2017-09-19
                    • 2015-02-24
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-05-03
                    • 1970-01-01
                    • 2011-04-27
                    • 1970-01-01
                    相关资源
                    最近更新 更多