序言;尝试让斐波那契更有效?

发布于 2024-10-03 12:20:04 字数 371 浏览 7 评论 0原文

这种逻辑编程确实让我的命令式编程技能大为提高。这是家庭作业,所以请不要给我答案。这就是我所拥有的:

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 技术交流群。

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

发布评论

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

评论(5

滥情空心 2024-10-10 12:20:04

我可以在这里发布解决方案,但由于这是家庭作业,因此会适得其反。相反,这是一个线索:

您列出的斐波那契版本的问题在于它效率低下。每次调用 fibo/2 都会引发另外的 two 调用,但其中一些调用会计算相同斐波那契数列的值。例如,在伪代码中:

(a) fibo(4) -> fibo(3), fibo(2)
(b) fibo(3) -> fibo(2), fibo(1)
(c) fibo(2) -> fibo(1), fibo(0) % called from (a)
(d) fibo(2) -> fibo(1), fibo(0) % called from (b), redundant

为了克服这一缺陷,我们要求您重新表述斐波那契数 据,不仅返回最后一个值,还返回最后两个值,以便每次调用 fib/3将仅导致一次递归调用(因此以线性时间计算斐波那契数列)。您需要将基本情况更改为:

fib(1,1,0).
fib(2,1,1).

我将把递归情况留给您。


对于不耐烦的人

来说,这也是递归情况:

fib(N, Val, Last) :-
  N > 2,
  N1 is N - 1,
  fib(N1, Last, Last1), % single call with two output arguments, 
                        % instead of two calls with one output argument
  Val is Last + Last1.

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:

(a) fibo(4) -> fibo(3), fibo(2)
(b) fibo(3) -> fibo(2), fibo(1)
(c) fibo(2) -> fibo(1), fibo(0) % called from (a)
(d) fibo(2) -> fibo(1), fibo(0) % called from (b), redundant

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:

fib(1,1,0).
fib(2,1,1).

I'll leave the recursive case to you.


For the impatient

Here is the recursive case as well:

fib(N, Val, Last) :-
  N > 2,
  N1 is N - 1,
  fib(N1, Last, Last1), % single call with two output arguments, 
                        % instead of two calls with one output argument
  Val is Last + Last1.
渡你暖光 2024-10-10 12:20:04

请参阅相关讨论:

用 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.

兮子 2024-10-10 12:20:04

也许使用尾递归是一个不错的选择

编辑:
您可以尝试类似 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

酒中人 2024-10-10 12:20:04

请记住,还有另一种计算斐波那契数列的方法:从基本情况开始向上移动。

现在,要计算 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 add fib(n-1) and fib(n-2). Instead, flip that around and calculate fib(0) and fib(1) based on the definition of the Fibonacci sequence, and build up from that.

晨曦慕雪 2024-10-10 12:20:04

你几乎已经拥有它了。只需重写:

fibo(N, Value) :-
N1 is N-1, N2 is N-2,
 fibo(N1, LastValue),fibo(N2, SecondToLastValue),
 Value is LastValue + SecondToLastValue.

fibo2(N, Value, LastValue):- ...

我不明白如何重写
这使用累积

就不要这样做,这不是必需的(尽管可以这样做)。

You almost already have it. Just rewrite:

fibo(N, Value) :-
N1 is N-1, N2 is N-2,
 fibo(N1, LastValue),fibo(N2, SecondToLastValue),
 Value is LastValue + SecondToLastValue.

in terms of

fibo2(N, Value, LastValue):- ...

I don't understand how I can rewrite
this using accumulation

Just don't, this is not needed (although it's possible to do so).

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