I'm currently studying for an exam in Prolog and so am trying to do some sample questions to get ready. I've been trying this one for while, the task it to create intgr/1 so that
?-intgr(X).
X=0;
X=1;
X=-1;
X=2;
X=-2;
...
What I have now is
intgr(0).
intgr(X) :- intgr(Y), (X is Y + 1 ; X is Y - 1).
However, it lists them out in a really weird way, namely:
X = 0
X = 1
X = -1
X = 2
X = 0
X = 0
X = -2
X = 3 ...
I'm just wondering what a good approach would be to change that in order to get them listed out in the right order.
Efficient:
intgr(I) :-
integer(I),
% Any integer will do, can stop here
!.
intgr(I) :-
var(I),
( I = 0
% Start alternating +/- with 1
; intgr_(1, I)
).
% Plus
intgr_(N, N).
% Minus
intgr_(N, I) :-
% Calc negative, rather than -(N) term
I is -N.
intgr_(N, I) :-
% Increment into infinity
N1 is N + 1,
intgr_(N1, I).
Results in swi-prolog:
?- intgr(-5).
true.
?- intgr(0).
true.
?- intgr(4).
true.
?- intgr(fish).
false. % Fails quickly, as appropriate
?- intgr(I).
?- intgr(I).
I = 0 ;
I = 1 ;
I = -1 ;
I = 2 ;
I = -2 ;
I = 3 ;
I = -3 ;
...
As @TA_intern pointed out, this can be shortened (if inf
is supported in between
) to:
intgr_between(I) :-
integer(I),
% Any integer will do, can stop here
!.
intgr_between(I) :-
var(I),
( I = 0
% Start alternating +/- with 1
; between(1, inf, N),
( I = N
; I is -N
)
).
Counting up to infinity can be implemented as e.g.:
incrementing_from(Start, N) :-
integer(N),
!,
integer(Start),
% Both variables are integer
N @>= Start.
incrementing_from(Start, N) :-
var(N),
integer(Start),
incrementing_from_(Start, N).
incrementing_from_(N, N).
incrementing_from_(U, N) :-
U1 is U + 1,
incrementing_from_(U1, N).