I'm new to Prolog, and using GNU Prolog, so no clp(fd) allowed. What I'm trying to do is for a given integer N, generate a list with elements of 1 ~ N. So set(3,T). will output T = [1,2,3].
Here is what I have so far:
set(0,[]).
set(N,T):-set(N-1,T1),append(T1,[N],T).
When I try set(2,T), it crashes. I debugged with trace, and find out that it's not evaluating N-1, but rather doing N-1-1-1...
Anyone can tell me how to solve this?
Thank you.
It should be:
set(N,T):- N2 is N-1, set(N2,T1), append(T1,[N],T).
Arithmetic operations are performed by using is/2
. N-1
is a shorthand for -(N,1)
(just like N2 is N-1
is shorthand for is(N2, N-1)
), so you were just creating infinite tree -(-(-(-(...),1),1,1,1)
.
Little educational note:
If you want set/2
to be proper relation so it can answer queries like set(3,X)
, set(X, [1,2,3])
and set(X,Y)
without error then you should write this predicate that way:
set(0, []).
set(Value, List) :-
length(List, Value),
append(ShorterList, [Value], List),
ValueMinusOne is Value - 1,
set(ValueMinusOne, ShorterList).
That way result of arithmetic operation is always possible to obtain because input value (lenght of the list) is either explicitly given or generated from length/1
.
n_ups(N, Xs) :-
length(Xs, N),
numbered_from(Xs, 1).
numbered_from([], _).
numbered_from([I0|Is], I0) :-
I1 is I0+1,
numbered_from(Is, I1).
In fact, the complexity is hidden within length/2
.