prolog - 在序言中对深层列表中的原子元素求和

标签 prolog

我是 Prolog 编程的初学者。我编写了这个程序来用累加器对深度列表的原子进行求和。

    deep_sum(Xs, N) :- deep_sum(Xs, 0, N).
    deep_sum([], N, N).
    deep_sum([X|Y], M, N) :- atomic(X), Q is M + X, deep_sum(Y, Q, N).
    deep_sum([X|Y], M, N) :- M is P + Q, deep_sum(X, P, N), deep_sum(Y, Q, N).

为什么我会收到“错误:is/2:参数没有充分实例化”?

它在没有累加器的情况下工作正常:
    deep_sum([], 0).
    deep_sum([X|Y], S) :- atomic(X), !, deep_sum(Y, Q), S is Q + X.
    deep_sum([X|Y], S) :- deep_sum(X, P), deep_sum(Y, Q), S is P + Q.

最佳答案

问题出在你的最后一个条款上:

deep_sum([X|Y], M, N) :-  M is P+Q, deep_sum(X,P,N), deep_sum(Y,Q,N).

错误的直接问题是当M is P+Q时P和Q都没有值。被执行。只是将它移到后面并不能解决它,该条款有更多问题。

让我们来看看递归调用。 deep_sum(X,P,N)在文字中的意思是“N 是头部 (X) 的深度总和,给定累加器 P”。这里有两个问题:P 没有值,N 应该是整个列表的总和,而不仅仅是头部。

在第二次递归调用中也存在同样的问题。累加器 Q 还没有值,而 N 再次用作结果。所以现在 N 有 3 种含义:头部的深度和,尾部的深度和,以及整个列表的深度和!显然有些地方不对劲。

让我们试着用语言表达递归规则应该如何表现。结果 N 应等于 a) 当前累加器、b) 头部的深度和和 c) 尾部的深度和的总和。 a 和 b 可以轻松组合:只需将当前累加器作为递归调用的累加器传入:deep_sum(X, M, N1) .这里我使用另一个变量 N1 来保存这个结果。现在我们只需要将其与尾部的深和相加即可。同样,我们可以简单地将 N1 作为递归调用的累加器传递,一切都将按预期进行累加。

将所有内容放在一起,您的递归规则应如下所示:
deep_sum([X|Y], M, N) :- 
    deep_sum(X, M, N1), 
    deep_sum(Y, N1, N).

为了完整起见,我的 deep_sum/3 实现看起来像这样:
deep_sum(X, M, N) :- 
    number(X), 
    N is M + X.
deep_sum([], N, N).
deep_sum([X|Y], M, N) :- 
    deep_sum(X, M, N1), 
    deep_sum(Y, N1, N).

主要区别是:
  • 只有一个递归子句;您处理数字的子句不需要是递归的。
  • number/1而不是 atomic/1 ,因此您不要尝试添加字符串等。
  • 重新排列子句的顺序,以免在计算完成后留下任何无用的选择点。
  • 关于prolog - 在序言中对深层列表中的原子元素求和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34284698/

    相关文章:

    Prolog 查询顺序和效率(trace 是否具有误导性?)

    module - 为什么 prolog 的 ISO 模块标准失败了?

    prolog - 什么东西永远不等于自己?

    prolog - Prolog 中的广度优先搜索

    prolog - 基于 Prolog 数据文件的多用户 Web 应用程序

    prolog - 罗森格兰茨夫人的杰西查询(斑马拼图)在 Prolog 中表达

    prolog - 关于解决意外 "Undefined procedure"错误的方法

    prolog - Prolog 中的命题逻辑子公式

    list - Prolog:元素不存在于列表中

    database - Prolog 数据库 : Why is program only running once?