I am new to using arithmetic in Prolog.
I’ve done a few small programs, but mostly involving logic. I am trying to implement a function that will return true
or false
if the difference between every consecutive pair of elements is the same or not.
My input would look like this: sameSeqDiffs([3, 5, 7, 9], 2)
I feel like I need to split the first two elements from the list, find their difference, and add the result to a new list. Once all the elements have been processed, check if the elements of the new list are all the same.
I’ve been taught some Prolog with building relationships and querying those, but this doesn’t seem to fit in with Prolog.
Update1: This is what I've come up with so far. I am brand new to this syntax and am still getting an error on my code, but I hope it conveys the general idea of what I'm trying to do.
diff([X,Y|Rest], Result):-
diff([Y,Z|Rest], Result2):-
Result2 = Result,
Z - Y = Result.
Update2: I know I still have much to do on this code, but here is where I will remain until this weekend, I have some other stuff to do. I think I understand the logic of it a bit more, and I think I need to figure out how to run the last line of the function only if there is at least two more things in the rest of the list to process.
diff([X,Y|Rest], Result):-
number(Y),
Y-X=Result,
diff([Rest], Result).
Update3: I believe I have the function the way I want it to. The only quirk I noticed is that when I run and input like: sameSeqDiffs([3,5,7],2).
I get true returned immediately followed by a false. Is this the correct operation or am I still missing something?
sameSeqDiffs([X,Y], Result):-
A is Y - X,
A = Result.
sameSeqDiffs([X,Y,Z|T], Result):-
sameSeqDiffs([Y,Z|T], Result).
Update 4: I posted a new question about this....here is the link: Output seems to only test the very last in the list for difference function
You were very close with your second attempt. It should have been
And you don't even need "to split the first two elements from the list". This will take care of itself.
How? Simple: calling
samediffs( List, D)
, on the first entry into the predicate, the not yet instantiatedD = Result
will be instantiated to the calculated difference between the second and the first element in the list by the callResult is Y - X
.On each subsequent entry into the predicate, which is to say, for each subsequent pair of elements
X
,Y
in the list, the callResult is Y - X
will calculate the difference for that pair, and will check the numerical equality for it andResult
which at this point holds the previously calculated value.In case they aren't equal, the predicate will fail.
In case they are, the recursion will continue.
The only thing missing is the base case for this recursion:
In case it was a singleton (or even empty) list all along, this will leave the differences argument
_Result
uninstantiated. It can be interpreted as a checking predicate, in such a case. There's certainly no unequal differences between elements in a singleton (or even more so, empty) list.In general, ......
...... Recursion!
Prolog's syntax
The syntax is a bit off: normally a clause has a head like
foo(X, Y, Z)
, then an arrow (:-
), followed by a body. That body normally does not contain any arrows:-
. So the second arrow:-
makes not much sense.Predicates and unification
Secondly in Prolog predicates have no input or output, a predicate is
true
orfalse
(well it can also error, or got stuck into an infinite loop, but that is typically behavior we want to avoid). It communicates answers by unifying variables. For example a callsameSeqDiffs([3, 5, 7, 9], X)
. can succeed by unifyingX
with2
, and then the predicate - given it is implemented correctly - will returntrue.
.Inductive definitions
In order to design a predicate, on typically first aims to come up with an inductive definition: a definition that consists out of one or more base cases, and one or more "recursive" cases (where the predicate is defined by parts of itself).
For example here we can say:
In Prolog this will look like:
(with the
___
to be filled in).Now for the inductive case we can define a
sameSeqDiffs/2
in terms of itself, although not with the same parameters of course. In mathematics, one sometimes defines a function f such that for example f(i) = 2×f(i-1); with for example f(0) = 1 as base. We can in a similar way define an inductive case forsameSeqDiffs/2
:In Prolog this will look like:
Arithmetic in Prolog
A common mistake people who start programming in Prolog make is they think that, like it is common in many programming languages, Prolog add semantics to certain functors.
For example one can think that
A - 1
will decrementA
. For Prolog this is however just-(A, 1)
, it is not minus, or anything else, just a functor. As a result Prolog will not evaluate such expressions. So if you writeX = A - 1
, thenX
is justX = -(A,1)
.Then how can we perform numerical operations? Prolog systems have a predicate
is/2
, that evaluates the right hand side by attaching semantics to the right hand side. So theis/2
predicate will interpret this(+)/2
,(-)/2
, etc. functors ((+)/2
as plus,(-)/2
as minus, etc.).So we can evaluate an expression like:
and then
X
will be set to3
, not4-1
. Prolog also allows to write theis
infix, like:Here you will need this to calculate the difference between two elements.