【问题标题】:How can I get this simple Prolog predicate to "return" the right way?我怎样才能让这个简单的 Prolog 谓词以正确的方式“返回”?
【发布时间】:2014-03-13 16:26:24
【问题描述】:

所以我正在学习 Prolog。我需要编写一个谓词来查找整数列表的最小值/最大值。例如,查询 minmaxArray([4,-1,5,4,1,2,3,-2],X,Y) 将返回 X = -2 Y = 5。这是我目前所拥有的:

    %min/max element of a 1 item list is that item.

    minmaxArray([X], X, X).

%when there is only 2 items, put the smaller element in A and the 
%larger element in B

    minmaxArray([X,Y], A, B) :- mymin(X,Y,Min), 
    A is Min, mymax(X,Y,Max), B is Max.

%when there is more than two items make a recursive call to find the min/max
%of the rest of the list.

    minmaxArray([X,Y|T], A, B) :- minmaxArray([Y|T], M, K), 
    mymin(X,M,Temp), A is Temp, mymax(X,K,Temp2), B is Temp2.

假设 mymin 和 mymax 谓词正常工作。它们返回 2 个数字的最小值和最大值。

这里的问题是,例如,当我查询 minmaxArray([4,-1,5],X,Y) 时,它返回 X = -1 Y = 5,然后再次返回 X = -1 Y = 5。我知道这一定是因为它在递归调用中达到了第二个条件。我只希望它返回 X = -1 Y = 5 一次。我尝试用这个替换条件 3:

minmaxArray([X,Y,_|T], A, B) :- minmaxArray([Y,_|T], M, K), 
    mymin(X,M,Temp), A is Temp, mymax(X,K,Temp2), B is Temp2.

但这会使程序崩溃。我能做些什么来解决这个问题?

注意:我知道我可能没有正确使用术语,比如说返回和说谓词什么时候应该是规则等等,所以我提前道歉。

【问题讨论】:

  • 你根本不需要is/2——你没有做任何算术。你可以说minmaxArray([X,Y], Min, Max) :- mymin(X,Y,Min), mymax(X,Y,Max).
  • 您可以使用min(X,Y) 内置为Min is min(X,Y) 来获取两个值中的最小值。 max 也是如此。这可能会让你的生活更简单一些。并且以@DanielLyons 评论为基础,不要使用is 来统一术语。使用=/2。例如,B = Temp2,而不是 B is Temp2。正如他所指出的,您可以通过在参数列表中统一它们来完全避免该步骤,如他的示例所示。
  • 好的,所以我对此完全陌生,这可能是一个愚蠢的问题,但是 =/2 是什么,当你说不使用 is 而使用 = 时,是因为 'is' 是当您想要评估算术运算时使用?谢谢!
  • 符号predicate/N 是带有arity(参数数量)的谓词的名称。 =/2=is/2is(这很容易阅读!)。 =/2 用于显式统一两个项,is/2 用于将左侧的变量或值与右侧算术表达式的计算结果统一。
  • 顺便说一句,“谓词”是正确的命名法,但“返回”不是。此外,您并没有使程序崩溃,它只是失败了。

标签: prolog


【解决方案1】:

似乎您的代码可以更简单。这个谓词做了所有需要的事情,并尝试展示如何使用一些标准结构(if/then/else)

minmaxArray([X], X, X).
minmaxArray([X|R], Min, Max) :-
    minmaxArray(R, Tmin, Tmax),
    ( X < Tmin -> Min = X ; Min = Tmin ), % or mymin(X,Tmin,Min)
    ( X > Tmax -> Max = X ; Max = Tmax ).

【讨论】:

  • 好的,感谢您提供清晰简洁的解决方案。我还在习惯 Prolog。
【解决方案2】:

您提供了 2 种方法来解决有 2 个项目的情况:一种明确用于 2 个项目,以及您的一般情况,然后使用 1 个元素的情况。

解决方案:删除不需要的 2 元素案例。

【讨论】:

  • 好的,感谢您指出这一点并提供有用的答案。当然是我犯的愚蠢错误!
  • 把它想象成一种成人仪式。
【解决方案3】:

或者,尾递归:

minmax([X|Xs],Min,Max) :- % we can only find the min/max of a non-empty list.
  minmax(Xs,(X,X),Min,Max)  % invoke the helper with the min/max accumulators seeded with the first item
  .

minmax([],(Min,Max),Min,Max).    % when the source list is exhausted, we're done: unify the accumulators with the result
minmax([X|Xs],(M,N),Min,Max) :-  % when the source list is non-empty
  min(X,M,M1) ,                  % - get a new min value for the accumulator
  max(X,N,N1) ,                  % - get a new max value for the accumulator
  minmax(Xs,(M1,N1),Min,Max)     % - recurse down on the tail.
  .

min(X,Y,X) :- X =< Y . % X is the min if it's less than or equal to Y.
min(X,Y,Y) :- X >  Y . % Y is the min if it's greater than X.

max(X,Y,X) :- X >= Y . % X is the max if it's greater than or equal to Y.
max(X,Y,Y) :- X <  Y . % Y is the max if it's greater than X.

【讨论】:

    猜你喜欢
    • 2021-02-10
    • 2019-06-13
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 2016-06-15
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多