🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.prolog
Article #3845

Queens Again

#3845
From: kale
Date: Tue, 03 Jan 1989 23:14
67 lines
3137 bytes

Here is a simple program for solving the n non-attacking program.
Unlike the usual ones I have seen and written, this program uses an
array of logical variables to keep track of the status of each diagonal.

It does not exploit any symmetries except the reflection-symmetry.
It uses an ADT for a set of logical variables, which is defined
by the two predicates createSet and bind.
This ADT is implemented here simply using a flat term (so is valid upto
the maximum arity allowed on your system. It was 128 on SBProlog).

I ran this with sbprolog and quintus, and it runs much faster than the simple
programs which do not keep track of the diagonals.

No originality claimed here. I remember reading postings by Saraswat
and possibly by H. Stone that may have involved similar algorithms.

This program showed me once more the advantage of programming in Prolog.
It took me 30-40 minutes to write, debug, and execute this.
I wrote the program later in C, and it took me about 4-5 hours.
(Of course, I may be a bad C programmer, am certainly rusty).
It is just the routine details one gets caught up in, in the C program.

Some peculiarities in the program are for compatibility with our
parallel (pure) prolog interpreter.

safe(N, Queens) :-
/* Queens is a set of N co-ordinates for N non attacking queens on a
   NxN board */
	makeList(N,Cols),
	N2 is 2*N+1,
	createSet(N2, Diag1),	/* Creates an "array" of logical variables */
	createSet(N2, Diag2),
	delete(Col,Cols, RCols), Nhalf is (N+1)/2, Col =< Nhalf,
	diag1of(1,Col, N, D1),     bind(Diag1, D1, 1),
	diag2of(1,Col, N, D2),     bind(Diag2, D2, 1),
	ext(2,N,[q(1,Col)], Diag1, Diag2, RCols, Queens).

ext(Row, Max, Selected, Diag1, Diag2, Cols, Selected) :- Row > Max.

ext(Row, Max, Selected, Diag1, Diag2, Cols, Final) :-
	Row =< Max,
	delete(Col, Cols, RCols), 
	diag1of(Row,Col, Max, D1), bind(Diag1, D1, Row),
	diag2of(Row,Col, Max, D2), bind(Diag2, D2, Row),
	N1 is Row+1, 
	ext(N1, Max, [q(Row,Col)|Selected], Diag1, Diag2, RCols, Final).

diag1of(Row, Col, Max, M) :- M is Row+Col-1.
  /* diag1of returns the diagonal number of one passing thru (Row,Col) */
diag2of(Row, Col, Max, M) :- M is Row-Col+Max.
  /* diag2of returns the diagonal number of the counter-diagonal
	 passing thru (Row,Col) */

/* createSet and bind define an ADT for an array of logical variables */
/* This implementation works only for sets of size < 128. */
/* That is enough here. In general, would need a tree.    */

createSet(Size,T) :- Size < 128, functor(T,f,Size).
bind(T,Position,Value) :- arg(Position,T,Value). 

delete(X, [X|R] , R).
delete(X, [Y|R] , [Y|T]) :- delete(X,R,T).

makeList(0,[]).
makeList(N,[N|R]) :- N>0, N1 is N-1, makeList(N1,R).
Technical Details
Message-ID: <5500009@m.cs.uiuc.edu>
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!lll-winken!lll-lcc!ames!mailrus!csd4.milw.wisc.edu!uxc!uxc.cso.uiuc.edu!m.cs.uiuc.edu!kale

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!lll-winken!lll-lcc!ames!mailrus!csd4.milw.wisc.edu!uxc!uxc.cso.uiuc.edu!m.cs.uiuc.edu!kale
From: kale@m.cs.uiuc.edu
Newsgroups: comp.lang.prolog
Subject: Queens Again
Message-ID: <5500009@m.cs.uiuc.edu>
Date: 3 Jan 89 23:14:00 GMT
Lines: 67
Nf-ID: #N:m.cs.uiuc.edu:5500009:000:2699
Nf-From: m.cs.uiuc.edu!kale    Jan  3 17:14:00 1989