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).
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.Each clause in the core works as follows:
Here's the code:
In prolog,
Doesn't actually do any arithmetic (I know, right?), it creates a structure:
And
is
is a predicate that evaluates that structure:Will unify X with
-1
.Also apparently
<
and>
(and those like it) are likeis
in that they evaluate expressions.So that means that the difference between your
fib
predicate and yourline
predicate is thatis using unification, ie, testing whether the terms themselves are equal:
Whereas a test like
=:=
tests for numerical equality: