【问题标题】:Prolog, triangular numbers, accumulators and tail recursionProlog、三角数、累加器和尾递归
【发布时间】:2011-06-30 08:44:07
【问题描述】:

我正在做一个家庭作业,由两部分组成。 首先是编写一个 Prolog 程序来检查某对 X、Y 是否属于 http://en.wikipedia.org/wiki/Triangular_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 谓词来解决这个问题。 虽然我在另一个分配中使用了累加器,其中的使用非常明显,所以我对如何使用累加器有一个大致的了解,但我对如何在这种情况下使用它感到很困惑。

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

【问题讨论】:

    标签: prolog tail-recursion accumulator triangular


    【解决方案1】:

    开头总是相同的,即前三行基本上是您为每个尾递归谓词编写的内容(使用[] 而不是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 个三角形数。

    【讨论】:

    • 啊,谢谢你。我想知道我的“正常”递归解决方案的尾递归性,因为就像你说的,我在算术之后调用了 triangle/2。感谢您也指出时间谓词:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 2012-05-26
    • 1970-01-01
    • 2012-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多