序言;尝试让斐波那契更有效?
这种逻辑编程确实让我的命令式编程技能大为提高。这是家庭作业,所以请不要给我答案。这就是我所拥有的:
fibo(N,1) :-
N < 2,
!.
fibo(N,R) :-
N1 is N-1,
N2 is N-2,
fibo(N1,R1),
fibo(N2,R2),
R is R1+R2.
我应该制作另一个看起来像这样的函数; fib(N,Value,LastValue)
。 N
是第 n 个数字,value 是返回值。我不明白如何使用累积来重写这个。而且由于它向后计数,我不明白它如何在计算任何内容之前“知道”最后一个值。 :s 任何意见都会受到赞赏。
This logic programming is really making a lap dance on my imperative programming skills. This is homework, so please just don't drop me the answer. This is what I have:
fibo(N,1) :-
N < 2,
!.
fibo(N,R) :-
N1 is N-1,
N2 is N-2,
fibo(N1,R1),
fibo(N2,R2),
R is R1+R2.
I'm suppose to make another function that looks like this; fib(N,Value,LastValue)
.N
is the n'th number, and value is the return value. I don't understand how I can rewrite this using accumulation. And since it counts backwards I don't see how it can "know" a last value before it calculates anything. :s Any input is appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我可以在这里发布解决方案,但由于这是家庭作业,因此会适得其反。相反,这是一个线索:
您列出的斐波那契版本的问题在于它效率低下。每次调用
fibo/2
都会引发另外的 two 调用,但其中一些调用会计算相同斐波那契数列的值。例如,在伪代码中:为了克服这一缺陷,我们要求您重新表述斐波那契数 据,不仅返回最后一个值,还返回最后两个值,以便每次调用
fib/3
将仅导致一次递归调用(因此以线性时间计算斐波那契数列)。您需要将基本情况更改为:我将把递归情况留给您。
对于不耐烦的人
来说,这也是递归情况:
I could post here the solution, but since that this is homework, it would be counter-productive. Instead, here's a lead:
The problem with the version of Fibonacci that you listed is that it is inefficient. Each call to
fibo/2
causes another two calls, but some of these calls calculate the values of the same Fibonacci numbers. For example, in pseudo-code:To overcome this deficiency, you were asked to rephrase Fibonacci in terms of returning not just the last value, but the last two values, so that each call to
fib/3
will cause only a single recursive call (hence calculate the Fibonacci series in linear time). You'll need to change the base cases to:I'll leave the recursive case to you.
For the impatient
Here is the recursive case as well:
请参阅相关讨论:
用 SICStus Prolog 概括斐波那契序列
并认为其中的非常好使用有限域约束的解决方案。
See the related discussion:
Generalizing Fibonacci sequence with SICStus Prolog
and consider ony's very good solution using finite domain constraints from there.
也许使用尾递归是一个不错的选择
编辑:
您可以尝试类似 fib(6) = fib(6,0,0) 的方法,而不是将 fib(6) 分解为 fib(5)+fib(4),第一个参数是步数,当它达到 0 时停止,第二个参数是你最后计算的值,第三个参数是要计算的值,它等于当前第二个和第三个参数的总和(第一步除外,其中 0 + 0 将是 1)
所以要计算,您在每次调用时设置第二个参数并在第三个参数中累积,因此 fib(6,0,0) => fib(5,0,1) =>; fib(4,1,1) =>; fib(3,1,2) =>; fib(2,2,3) =>; fib(1,3,5) =>; fib(0,5,8) 然后返回 8
在该方法中,您实际上不必将返回的地址保存在堆栈中,避免堆栈溢出
Perhaps using tail recursion is a good option
edit:
Instead of breaking fib(6) into fib(5)+fib(4) you might try something like fib(6) = fib(6,0,0) the first parameter is the count of steps, when it reaches 0 you stop, the second parameter the last value you calculated, and the third parameter is the value to calculate which is equal to the sum of current second and third parameters (with the exception of the first step, in which 0 + 0 will be 1)
So to calculate you set the second parameter at each call and acumulate in the third so fib(6,0,0) => fib(5,0,1) => fib(4,1,1) => fib(3,1,2) => fib(2,2,3) => fib(1,3,5) => fib(0,5,8) then you return 8
In that method you dont actually have to save in the stack the adress return, avoiding stack overflow
请记住,还有另一种计算斐波那契数列的方法:从基本情况开始向上移动。
现在,要计算
fib(n)
,请添加fib(n-1)
和fib(n-2)
。相反,将其翻转并根据斐波那契数列的定义计算fib(0)
和fib(1)
,并以此为基础进行构建。Remember that there is another way to calculate the Fibonacci sequence: starting from the base case and moving up.
Right now, to calculate
fib(n)
, you addfib(n-1)
andfib(n-2)
. Instead, flip that around and calculatefib(0)
andfib(1)
based on the definition of the Fibonacci sequence, and build up from that.你几乎已经拥有它了。只需重写:
就
就不要这样做,这不是必需的(尽管可以这样做)。
You almost already have it. Just rewrite:
in terms of
Just don't, this is not needed (although it's possible to do so).