% generated: 10 November 1989
% option(s):
%
% (queens) queens_8
%
% from Sterling and Shapiro, "The Art of Prolog," page 211.
%
% solve the 8 queens problem
queens_8 :- queens(8,_), !.
% This program solves the N queens problem: place N pieces on an N
% by N rectangular board so that no two pieces are on the same line
% - horizontal, vertical, or diagonal. (N queens so placed on an N
% by N chessboard are unable to attack each other in a single move
% under the rules of chess.) The strategy is incremental generate-
% and-test.
%
% A solution is specified by a permutation of the list of numbers 1 to
% N. The first element of the list is the row number for the queen in
% the first column, the second element is the row number for the queen
% in the second column, et cetera. This scheme implicitly incorporates
% the observation that any solution of the problem has exactly one queen
% in each column.
%
% The program distinguishes symmetric solutions. For example,
%
% ?- queens(4, Qs).
%
% produces
%
% Qs = [3,1,4,2] ;
%
% Qs = [2,4,1,3]
queens(N,Qs) :-
range(1,N,Ns),
queens(Ns,[],Qs).
queens([],Qs,Qs).
queens(UnplacedQs,SafeQs,Qs) :-
select(UnplacedQs,UnplacedQs1,Q),
not_attack(SafeQs,Q),
queens(UnplacedQs1,[Q|SafeQs],Qs).
not_attack(Xs,X) :-
not_attack(Xs,X,1).
not_attack([],_,_) :- !.
not_attack([Y|Ys],X,N) :-
X =\= Y+N, X =\= Y-N,
N1 is N+1,
not_attack(Ys,X,N1).
select([X|Xs],Xs,X).
select([Y|Ys],[Y|Zs],X) :- select(Ys,Zs,X).
range(N,N,[N]) :- !.
range(M,N,[M|Ns]) :-
M < N,
M1 is M+1,
range(M1,N,Ns).