【问题标题】:Getting the minimum value of a list获取列表的最小值
【发布时间】:2011-12-24 03:03:00
【问题描述】:

我试图找到一个列表的最小值(作为学习经验,所以没有min)。

我的方法如下:

minimo([X], X).
minimo([X,Y|Tail], N):-
    (X > Y, minimo([Y,Tail], Y));
    (X <= Y, minimo([X,Tail], X)).

这给了我以下错误:

语法错误:需要运算符

所以我的问题是:

  • 导致语法错误的原因是什么?
  • 如果它确实返回了正确的值,我会在修复后自己尝试,但这真的是正确的方法吗?

提前致谢。

【问题讨论】:

    标签: list prolog syntax-error minimum iso-prolog


    【解决方案1】:

    除了已经发布的其他版本之外,还可以考虑一个没有 if-then-else 的版本,并为关系使用更具描述性的名称(将列表与其最小值相关联):

    list_min([L|Ls], Min) :- list_min(Ls, L, Min).
    
    list_min([], Min, Min).
    list_min([L|Ls], Min0, Min) :-
        Min1 is min(L, Min0),
        list_min(Ls, Min1, Min).
    

    这样的模式称为折叠(从左至右),我们可以用`foldl/4等效地写它:

    list_min([L|Ls], Min) :- foldl(min_, Ls, L, Min).
    
    min_(A, B, Min) :- Min is min(A, B).
    

    查询示例:

    ?- list_min([1,0,2], Min).
    Min = 0.
    

    请注意,虽然这不是一个真正的关系,并且由于使用了低级算术,因此不能在所有方向上使用。例如,如果我们尝试在另一个方向使用它,我们会得到:

    ?- list_min([X,Y], 3)。 ERROR: is/2: 参数没有充分实例化

    要使其成为真正的解决方案,请使用 约束,例如 。例如,对于 整数 的解决方案:

    :- use_module(library(clpfd)).
    
    list_min([L|Ls], Min) :- foldl(min_, Ls, L, Min).
    
    min_(A, B, Min) :- Min #= min(A, B).
    

    这适用于所有方向:

    ?- list_min([X,Y], 3).
    X in 3..sup,
    3#=min(Y, X),
    Y in 3..sup.
    

    【讨论】:

      【解决方案2】:
      min([H|T], Min) :- min(T, H, Min).
      
      min([], Min, Min).
      min([H|T], Min, Min1) :-
        (   H < Min
        ->  min(T, H, Min1)
        ;   min(T, Min, Min1) ).
      

      【讨论】:

        【解决方案3】:

        您的程序中有几个错误:

        1. 正如 Joe Lehmann 所指出的,没有'&lt;='/2。必须是'=&lt;'/2

        2. 当您递归调用minimo/2 时,您构建的列表是错误的。而不是[Y,Tail] 使用[Y|Tail]。否则,您会得到一个列表,其中列表作为第二个元素。

        3. 您将minimo/2 的递归调用的第二个参数绑定到YX。相反,它必须绑定到N。否则,您的N 将永远不会被实例化。

        您可以通过添加剪辑或使用 if-then-else ('-&gt;' + ;) 来进一步改进您的程序:

        minimo([X], X) :- !.
        minimo([X,Y|Tail], N):-
            ( X > Y ->
                minimo([Y|Tail], N)
            ;
                minimo([X|Tail], N)
            ).
        

        【讨论】:

          【解决方案4】:

          语法错误是,因为Prolog中的小于等于=

          我认为这种方法会奏效,但您确实应该避免使用 ;在一个子句中。把它分成两个子句。

          另外我认为你想在递归中做类似 [X|Tail] 而不是 [X,Tail] 的事情

          【讨论】:

          • =&lt; 似乎已修复,谢谢。但现在我得到了这个错误:ERROR: &gt;/2: Arithmetic: []/0' is not a function``当我把它分成两部分时,我得到:- minimo([1,2,3],X). ERROR: &gt;/2: Arithmetic: `[]/0' is not a function Exception: (8) minimo([[3], []], [3]) ?谢谢! +1
          猜你喜欢
          • 2015-09-26
          • 2022-01-25
          • 2020-09-22
          • 2021-09-17
          • 2014-03-25
          • 2017-05-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多