[comp.lang.prolog] N-queens revisited

jm@sics.se (Johan Montelius) (08/03/90)

This is yet another n-queens solver. It illustrates the concept of
using logical variables as communication channels. In this case they
are simple flags but the concept has general usage for any information
that need to be spread out immediately to different parts of a program.

Really there is nothing special about this, logical variables work
this way all the time ;-) but this example could maybe be of some 
interest to novice prolog users.

There is no attempt to reduce the combinatorial work in the queens
problem, this is just a fast way to do the work.


A 4*4 board is created like:

	[[p(C1, _,Y1),p(C2,X2,Y2),p(C3,X3,Y3),p(C4,X4, _)],
	 [p(C1,X2,Y4),p(C2,X3,Y1),p(C3,X4,Y2),p(C4,X5,Y3)],
	 [p(C1,X3,Y5),p(C2,X4,Y4),p(C3,X5,Y1),p(C4,X6,Y2)],
	 [p(C1,X4, _),p(C2,X5,Y5),p(C3,X6,Y4),p(C4, _,Y1)]]

All positions in the same column or diagonal share a variable. 
When queen n is placed at a position the structure p(C,X,Y) is
instantiated to p(n,n,n). Queen n+1 can then not be placed at
any position on the same column or diagonal as queen n, since
p(n+1,n+1,n+1) will not unify with p(n,_,_), p(_,n,_) or p(_,_n).

Johan Montelius
jm@sics.se

Kent Boortz
boortz@sics.se


%%%%	Yet another N-Queens program
%%%%	By Johan Montelius and Kent Boortz
%%%%
%%%%	:- queens(+Number of Queens, -The table).
%%%%	:- timeall(queens(8, _)) => 0.2 s (SICStus with spark native code)

queens(N,All):- board(N,N,All),place(All,1).

board(1,_,[_]).
board(M,N,[Next,Last|Rest]):-
	M =\= 1,
	M1 is M - 1,
	next(N,Last,Next),
	board(M1,N,[Last|Rest]).

next(1,[_],[_]).
next(N,[p(A2,B2,_),p(A1,B1,C2)|Rest],[p(A2,_,C2),p(A1,B2,C3)|Next]):- 
	N =\= 1,
	N1 is N - 1,
	next(N1,[p(A1,B1,C2)|Rest],[p(A1,B2,C3)|Next]). 

place([],_).
place([Row|Rest],N):-
	row(Row,N),
	N1 is N + 1,
	place(Rest,N1).

row([p(N,N,N)|_],N).
row([_|Row],N) :- row(Row,N).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

display_queens(N) :- queens(N,All),displ(All).

displ([First|_]):- displr(First).
displr([]).
displr([p(C,_,_)|Rest]):- write(C),write(' '),displr(Rest).

time(Goal):- 
	statistics(runtime,_),
	call(Goal),
	statistics(runtime,[_,T]),
	Sec is T / 1000,
	nl,write(Sec),write(' sec.'),nl.

timeall(Goal):- time(all(Goal)).

all(Goal):- call(Goal),fail.
all(_).


--
Johan Montelius 
SICS, PO Box 1263, S-164 28 Kista, Sweden.	
Phone: +46 8 752 15 68     Telefax: +46 8 751 72 30       Internet: jm@sics.se