【问题标题】:Sum the atomic elements in a deep list in prolog在 prolog 的深度列表中求和原子元素
【发布时间】:2015-12-15 08:52:45
【问题描述】:

我是 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.

【问题讨论】:

  • 请添加示例查询,尤其是显示该错误的查询。

标签: prolog


【解决方案1】:

问题在于你的最后一个子句:

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,所以你不要尝试添加字符串左右。
  • 重新排列子句的顺序,以免在计算完成后留下任何无用的选择点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多