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

Prolog、三角数、累加器和尾部递归,prolog,tail-recursion,accumulator,triangular,Prolog,Tail Recursion,Accumulator,Triangular,我正在做一个家庭作业,由两部分组成。 第一种方法是编写一个Prolog程序,检查某对X,Y是否属于某个对象。例如:(2,3)=真;(4,10)=真的等等 第一个解决方案使用“普通”递归,我这样解决: triangle(0, 0). triangle(X, Y) :- X > 0, Y > 0, A is X - 1, B is Y - X, triangle(A, B). 第二部分是使用尾部递归/累加器,使用三角形/3谓词来解决这个问题。 虽然我在另一个任务中使用了累加器,在这个任

我正在做一个家庭作业,由两部分组成。 第一种方法是编写一个Prolog程序,检查某对X,Y是否属于某个对象。例如:(2,3)=真;(4,10)=真的等等

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

triangle(0, 0).
triangle(X, Y) :- X > 0, Y > 0, A is X - 1, B is Y - X, triangle(A, B).
第二部分是使用尾部递归/累加器,使用三角形/3谓词来解决这个问题。 虽然我在另一个任务中使用了累加器,在这个任务中,累加器的用法非常明显,所以我对如何使用累加器有一个大致的概念,但在这个上下文中如何使用它,我感到非常困惑


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

开始总是相同的,即前三行基本上是您为每个尾部递归谓词编写的内容(列表谓词使用
[]
而不是
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\u t
谓词中引入这一行,它们又具有完全相同的运行时特征:

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

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

Ah,谢谢。我想知道我的“正常”递归解决方案的尾部递归性,因为就像你说的,我在做算术后调用三角形/2。感谢您指出时间:)