Prolog、三角数、累加器和尾递归

发布于 2024-10-18 04:43:59 字数 543 浏览 6 评论 0原文

我正在做一项家庭作业,由两部分组成。 第一个是编写一个 Prolog 程序,检查某个对 X, Y 是否属于 http://en .wikipedia.org/wiki/Triangle_number。例如:(2, 3) = true; (4, 10) = true 等等。

第一个解决方案使用“普通”递归,我已经这样解决了这个问题:

triangle(0, 0).
triangle(X, Y) :- X > 0, Y > 0, A is X - 1, B is Y - X, triangle(A, B).

第二部分是使用尾递归/累加器,使用三角形/3谓词来解决这个问题。 虽然我在另一个作业中使用过累加器,其中的用法非常明显,所以我对如何使用累加器有一个大致的了解,但我对如何在这种情况下使用它感到非常困惑。

所以,我不是在寻找算法,我宁愿自己解决这个问题,而是更多关于如何在这种情况下应用累加器的实用建议。

I'm working on a homework assignment, consisting of 2 parts.
The first is to write a Prolog program that checks if a certain pair X, Y belongs to a http://en.wikipedia.org/wiki/Triangular_number. For example: (2, 3) = true; (4, 10) = true et cetera.

The first solution uses 'ordinary' recursion, and I've solved this like this:

triangle(0, 0).
triangle(X, Y) :- X > 0, Y > 0, A is X - 1, B is Y - X, triangle(A, B).

The second part is to solve this using tail recursion/an accumulator, using a triangle/3 predicate.
Though I have used an accumulator in another assigment, in which the use was quite obvious, so I have a general idea of how to use an accumulator, I'm quite puzzeled as to how to use it in this context.

So, I'm not looking for an algorithm, I'd much rather solve that myself, but more of a practical advise on how to apply an accumulator in this context.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

悟红尘 2024-10-25 04:43:59

开头始终相同,即前三行基本上是您为每个尾递归谓词编写的内容(对于列表谓词,使用 [] 而不是 0 )。

从这里开始,您可以继续进行,无需进行太多更改:

 triangle_t(X, Y) :- triangle_t(X, 0, Y).
 triangle_t(0, Y, Y).
 triangle_t(X, Acc, Y) :-
          X > 0,
          A is X - 1,
          AccX is Acc + X,
          triangle_t(A, AccX, Y).

以下是大 X 的一些统计数据:

64 ?- time(triangle(1000000,500000500000)).
% 4,000,000 inferences, 0.50 CPU in 0.52 seconds (96% CPU, 8012769 Lips)
true.

65 ?- time(triangle_t(1000000,500000500000)).
% 3,000,001 inferences, 0.41 CPU in 0.44 seconds (92% CPU, 7396405 Lips)
true.

因此,虽然您自己的谓词基本上已经是尾递归(因为递归调用是最后要做的事情),但带有累加器的版本仍然节省了一些时间因为您不需要检查 Y > 0 。如果您在 triangle_t 谓词中引入这一行,它们将再次具有完全相同的运行时特征:

67 ?- time(triangle_t(1000000,500000500000)).
% 4,000,001 inferences, 0.53 CPU in 0.53 seconds (100% CPU, 7541432 Lips)
true.

另请注意,您现在可以使用谓词来生成第 n 个三角形数。

The beginning is always the same, i.e. the first three lines are basically what you write for each and every tail recursive predicate (with a [] instead of a 0 for list predicates).

From there you can go on without many changes:

 triangle_t(X, Y) :- triangle_t(X, 0, Y).
 triangle_t(0, Y, Y).
 triangle_t(X, Acc, Y) :-
          X > 0,
          A is X - 1,
          AccX is Acc + X,
          triangle_t(A, AccX, Y).

Here are some statistics for large X:

64 ?- time(triangle(1000000,500000500000)).
% 4,000,000 inferences, 0.50 CPU in 0.52 seconds (96% CPU, 8012769 Lips)
true.

65 ?- time(triangle_t(1000000,500000500000)).
% 3,000,001 inferences, 0.41 CPU in 0.44 seconds (92% CPU, 7396405 Lips)
true.

So, while your own predicate is basically already tail recursive (because the recursive call is the last thing to do) the version with an accumulator still saves some time because you do not need the check for Y > 0. If you introduce this line in the triangle_t predicate, they have exactly the same runtime characteristics again:

67 ?- time(triangle_t(1000000,500000500000)).
% 4,000,001 inferences, 0.53 CPU in 0.53 seconds (100% CPU, 7541432 Lips)
true.

Also note that you can now use the predicate to generate the n'th triangular number.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文