Reputation: 605
The following code is giving me a fatal local stack overflow error (after all solutions are found, instead of "no"), and I don't understand why. I'm pretty sure that it has something to do with the range
predicate, since if I replace it with a list, I don't have the issue, but I don't understand how it's causing an overflow.
nqueens(N,X) :-
pattern(N,X),range(N,Yrange),legal(Yrange,X).
nocheck(_, []).
nocheck(X/Y, [X1/Y1 | Rest]) :-
Y =\= Y1,
abs(Y1-Y) =\= abs(X1-X),
nocheck(X/Y, Rest).
legal(_,[]).
legal(Yrange,[X/Y | Rest]) :-
legal(Yrange,Rest),
member(Y,Yrange),
nocheck(X/Y, Rest).
pattern(1,[1/_]).
pattern(N,[N/_|T]) :- N1 is N-1,pattern(N1,T).
range(1,[1]).
range(N,[N|T]) :- N1 is N-1,range(N1,T).
Upvotes: 1
Views: 968
Reputation: 60034
When N in range/2 becomes 1, the following clause should not be left for eventual further processing (that will happen on backtracking), since it will become negative and the recursion will not stop anymore. You can either test for positiveness in the second clause
range(N,[N|T]) :- N>0,N1 is N-1,range(N1,T).
or - I think - just cut after the first one
range(1,[1]) :- !.
Another possibility would be to make the predicate deterministic at call point:
nqueens(N,X) :-
pattern(N,X),once(range(N,Yrange)),legal(Yrange,X).
Upvotes: 1