Prolog:递减参数中的变量

发布于 2024-12-01 23:34:35 字数 1220 浏览 2 评论 0原文

我是 Prolog 新手,任务是处理斐波那契谓词 fib( N, F),其中 N 是序列中的数字,F 是值。我想出的方法不起作用,但我找到的解决方案对我来说似乎相同......我无法理解其中的区别。

我的版本:

/* MY VERSION, DOES NOT WORK */
fib( 0, 0).
fib( 1, 1).
fib(N,F) :-
    N > 1,
    fib(N-1,F1),
    fib(N-2,F2),
    plus(F1,F2,F).

工作版本:

/* FOUND SOLUTION, DOES WORK */
fib( 0, 0).
fib( 1, 1).
fib(N,F) :-
    N > 1,
    N1 is N-1,
    N2 is N-2,
    fib(N1,F1),
    fib(N2,F2),
    plus(F1,F2,F).

显然,问题与我使用“N-1”和“N-2”作为参数而不是首先将这些值分配给新变量有关。但我不明白......因为在其他递归 Prolog 代码中,我已经成功地做到了这一点(在参数槽中减少了一个变量)。这有道理吗?

谢谢!


下面是“N-1”起作用的示例。

line( N, _, _) :-
    N =:= 0.

line( N, M, Char) :-
    N > 0,
    N mod M =\= 1,
    write( Char), write( ' '),
    line( N-1, M, Char).

line( N, M, Char) :-
    N > 0,
    N mod M =:= 1,
    write( Char), write( '\n'),
    line( N-1, M, Char).

square( N, Char) :-
    N > 0,
    line( N*N, N, Char).

新版本的 fib/2 也可以使用!

/* NEW VERSION, CHANGED TRIVIAL CASES TO EVALUATE N */
fib( N, 0) :-
    N =:= 0.

fib( N, 1).
    N =:= 1.

fib(N,F) :-
    N > 1,
    fib(N-1,F1),
    fib(N-2,F2),
    plus(F1,F2,F).

I am new to Prolog and was tasked with a Fibonnaci predicate fib( N, F) where N is the number in sequence, and F is the value. What I came up with does not work, but the solution I found seems identical to me... I cannot understand the difference.

My version:

/* MY VERSION, DOES NOT WORK */
fib( 0, 0).
fib( 1, 1).
fib(N,F) :-
    N > 1,
    fib(N-1,F1),
    fib(N-2,F2),
    plus(F1,F2,F).

The working version:

/* FOUND SOLUTION, DOES WORK */
fib( 0, 0).
fib( 1, 1).
fib(N,F) :-
    N > 1,
    N1 is N-1,
    N2 is N-2,
    fib(N1,F1),
    fib(N2,F2),
    plus(F1,F2,F).

Obviously the problem has something to do with me using "N-1" and "N-2" as arguments rather than assigning those values to new variables first. But I don't get it... because in other recursive Prolog codes, I have successfully done just that (decremented a variable right in the argument slot). Does this make sense?

Thanks!


Below is an example where the "N-1" did work.

line( N, _, _) :-
    N =:= 0.

line( N, M, Char) :-
    N > 0,
    N mod M =\= 1,
    write( Char), write( ' '),
    line( N-1, M, Char).

line( N, M, Char) :-
    N > 0,
    N mod M =:= 1,
    write( Char), write( '\n'),
    line( N-1, M, Char).

square( N, Char) :-
    N > 0,
    line( N*N, N, Char).

A new version of fib/2 which also works!

/* NEW VERSION, CHANGED TRIVIAL CASES TO EVALUATE N */
fib( N, 0) :-
    N =:= 0.

fib( N, 1).
    N =:= 1.

fib(N,F) :-
    N > 1,
    fib(N-1,F1),
    fib(N-2,F2),
    plus(F1,F2,F).

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

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

发布评论

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

评论(2

仲春光 2024-12-08 23:34:35

在序言中,

1 - 2

实际上并没有做任何算术(我知道,对吧?),它创建了一个结构:

-(1, 2)

is 是一个评估该结构的谓词:

is(X, -(1, 2))

Will unify X with -1< /代码>。

显然也 <> (以及类似的) 就像 is因为他们评估表达式。

因此,这意味着 fib 谓词和 line 谓词之间的区别在于

fib(0, 0).

使用统一,即测试术语本身是否相等:

foo(0).

?- foo(1 - 1).
false

而像 这样的测试>=:= 测试数值相等:

foo(X) :- X =:= 0.

?- foo(1 - 1).
yes

In prolog,

1 - 2

Doesn't actually do any arithmetic (I know, right?), it creates a structure:

-(1, 2)

And is is a predicate that evaluates that structure:

is(X, -(1, 2))

Will unify X with -1.

Also apparently < and > (and those like it) are like is in that they evaluate expressions.

So that means that the difference between your fib predicate and your line predicate is that

fib(0, 0).

is using unification, ie, testing whether the terms themselves are equal:

foo(0).

?- foo(1 - 1).
false

Whereas a test like =:= tests for numerical equality:

foo(X) :- X =:= 0.

?- foo(1 - 1).
yes
痕至 2024-12-08 23:34:35

我可能会编写如下所示的谓词。

fib/2 是外部“公共”接口。 N 是序列中的位置(零相对)。 F 与该位置的斐波那契数列值统一。

fibonacci/5 是完成这项工作的内部“核心”。

  • 第一个参数是计数器
  • 第二个参数是限制
  • 第三/第四个参数是计算序列中下一项所需的滑动框架。应该注意的是,斐波那契数列不需要以{1,1}开始。任何两个整数都可以。
  • 第 5 个参数与期望的结果统一。

核心中的每个子句的工作原理如下:

  • 如果N为0,则F统一为“1”。
  • 如果N为1,则F统一为“1”。
  • 如果达到了限制,我们就完成了。将 F 与序列中前两个元素的总和统一。
  • 如果计数器小于限制,则计算序列中的下一个元素并递归,将最旧的值从滑动窗口中滑出。

这是代码:

fib( N , F ) :-
  N >= 0 ,
  fibonnaci( 0 , N , 1 , 1 , F ).

fibonacci( 0     , 0     , F , _ , F ).
fibonacci( 1     , 1     , _ , F , F ).
fibonacci( Limit , Limit , X , Y , F ) :-
  F is X + Y
  .
fibonacci( Current , Limit , X , Y , F ) :-
  Current < Limit ,
  Next is Current + 1 ,
  Z is X + Y ,
  fibonacci( Next , Limit , Y , Z , F )
  .

I'd probably write the predicate somthing like the following.

fib/2 is the outer 'public' interface. N is the position in the sequence (zero-relative). F gets unified with the value of the Fibonacci sequence at that position.

fibonacci/5 is the inner 'core' that does the work.

  • The 1st argument is the counter
  • The 2nd argument is the limit
  • The 3rd/4th arguments are the sliding frame required to compute the next item in the sequence. It should be noted that there is not required for a Fibonacci sequence start start with { 1 , 1 }. Any two integers will do.
  • The 5th argument gets unified with the desired result.

Each clause in the core works as follows:

  • If N is 0, F is unified with '1'.
  • If N is 1, F is unified with '1'.
  • If the limit has been reached, we're done. Unify F with the sum of the preceding two elements in the sequence.
  • If counter is less than the limit, compute the next element in the sequence and recurse, sliding the oldest value out from the sliding window.

Here's the code:

fib( N , F ) :-
  N >= 0 ,
  fibonnaci( 0 , N , 1 , 1 , F ).

fibonacci( 0     , 0     , F , _ , F ).
fibonacci( 1     , 1     , _ , F , F ).
fibonacci( Limit , Limit , X , Y , F ) :-
  F is X + Y
  .
fibonacci( Current , Limit , X , Y , F ) :-
  Current < Limit ,
  Next is Current + 1 ,
  Z is X + Y ,
  fibonacci( Next , Limit , Y , Z , F )
  .
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文