【问题标题】:How to check if each element in Prolog list is greater than 0?如何检查Prolog列表中的每个元素是否大于0?
【发布时间】:2013-02-07 03:28:04
【问题描述】:

我有以下 Prolog 谓词原型:solution(+InputVector),其中 InputVector 是长度未知的值的列表。如果列表中的所有值都大于 0,我会打印出一条消息。我该怎么做呢?

【问题讨论】:

  • 您已经在问题中描述了解决方案...
  • 我是 prolog 的新手,我的教授不是最好的老师,所以我真的只是在猜测和测试。这是我迄今为止尝试过的一个示例:solution([X|Y]) :- X > 0. solution([_|Y]) :- solution(Y)。
  • 您没有处理空列表[],如果任何 个数字大于零,而不是全部大于零,您的解决方案将成功。

标签: list recursion prolog


【解决方案1】:

如果您有兴趣将您的学习扩展到“高阶”谓词,请考虑maplist/2:

3 ?- maplist(<(0), [1,2,3]).
true.

4 ?- maplist(<(0),[0,1,2,3]).
false.

【讨论】:

    【解决方案2】:

    尝试检查列表是 [] 还是 [X|Xs],然后采取相应措施。

    【讨论】:

    • 我对 prolog 完全陌生,所以语法本身对我来说完全陌生。
    【解决方案3】:

    你快到了。考虑以下内容(感谢@aBathologist 更新):

      1|  solution([X]) :- 
      2|     X > 0, 
      3|     !,
      4|     write_ln('Success!').
      5|  solution([X|Y]) :- 
      6|     X > 0,
      7|     solution(Y).
    

    让我们逐行考虑这实际上是如何工作的:

    1. 定义谓词solution/1 的第一个子句,它接受一个包含X 作为参数的单元素 列表。
    2. 测试项目X 是否为&gt; 0 的数字。如果不是,谓词将在此处终止并失败。否则,Prolog 将继续下一行。
    3. 虽然不是绝对必要的,但此处的剪切 (!) 删除了 Prolog 在 (1) 处生成的选择点,因为第 (6) 行的第二个子句也可以使用输入 [X] 执行,因为这相当于[X|Y],其中Y = []。因此,这只是为了提高效率而进行的所谓“粗略”切割。
    4. 由于列表 [X] 包含所有大于零的元素,谓词打印一条消息并成功。
    5. 定义谓词solution/1 的第二个子句,它接受一个包含一个或多个 项的列表,其中X 是列表的头部,Y 是尾部(其余) 的列表(它本身就是一个可能为空的列表:[])。
    6. 与第 (2) 行相同。
    7. 继续递归测试列表的其余部分,Y

    请注意,上述定义假定solution/1 必须仅在非空大于零的数字列表上成功。如果您希望允许此谓词在空列表上成功,则可以使实现更加简单:

    solution([]) :- 
        write_ln('Success!').
    solution([X|Y]) :-
        X > 0, 
        solution(Y).
    

    在这个版本中,solution/1 的两个子句中的任何一个都根据参数执行:第一个处理空列表,第二个处理更大的数字的非空列表比零。此处不需要剪切 (!),因为谓词参数是不可统一的 ([] \= [X|Y]),并且 Prolog 不会为第一个子句的任何调用生成选择点。

    我希望这对您有所帮助,并使 Prolog 语法的一些语义对您来说更加清晰。

    【讨论】:

    • 同样,如果原始输入列表为空,这将失败,这可能不是预期的。此外,没有 if-then-else 似乎更简洁。
    • 您可以排除没有-&gt; 的空列表,因此:solution([Val]) :- Val &gt; 0 , write_ln('Solved'). solution([Val | Vals]) :- Val &gt; 0 solution(Vals)
    • @aBathologist 你说得对,谢谢!我会更新答案,因为我更喜欢这个,因为它简化了描述(特别是针对假设空列表可以的替代方案)。
    • @sharky 我很高兴我能做出有用的贡献!我有两个问题,以防你有时间回答:首先,我对 Prolog 很陌生,还没有开始探索削减,所以它在这里的使用对我来说仍然有点不清楚,但我已经不知何故形成了一种偏见,即最好尽可能避免使用它们,因为它们增加了声明性方法的“杂质”。有没有道理呢?其次,您能否避免第 5 行中的歧义与 [X, Y | []]?
    • @aBathologist 虽然削减确实使 Prolog 程序不纯,但在实践中(例如对于现实世界的 Prolog 编程)削减通常对效率至关重要。如果您正在进行任何严肃的 Prolog 编程,我建议您了解如何以及何时正确使用 cuts。另外,[X|Y] != [X, Y | []]。列表符号中的条形 | 将头部 元素 (LHS) 与尾部 list (RHS) 分开。在[X|Y]中,X是头元素,Y是任意长度的尾列表,而[X, Y | []]表示长度为2的列表。
    【解决方案4】:

    我会这样写谓词:

    all_greater_than_zero([]).
    all_greater_than_zero([H|T]) :-
        H > 0,
        all_greater_than_zero(T).
    

    我认为空列表是可以接受的。如果没有,您可以删除第一个子句。

    【讨论】:

    • 如果一个空列表可以接受,如果所有元素都是&gt; 0,那么简单地删除示例中的第一个子句如何允许OP根据需要“打印一条消息” ?
    猜你喜欢
    • 2018-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多