
safe(N,Final) :-
	makeList(N,Cols),
	N2 is 2*N+1,
	createSet(N2, Diag1),
	createSet(N2, Diag2),
	delete(Col,Cols, RCols), Nhalf is (N+1)/2, Col =< Nhalf,
	Nforth is (Nhalf+1)/2, Col >= Nforth,
/*	write(deleting), nl,  */
	diag1of(1,Col, N, D1), bind(Diag1, D1, 1),
	diag2of(1,Col, N, D2), bind(Diag2, D2, 1),
/*	write(recur), nl, */
	ext(2,N,[q(1,Col)], Diag1, Diag2, RCols, Final).

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

ext(Row, Max, Selected, Diag1, Diag2, Cols, Final) :-
	Row =< Max,
/*	write(row(Row)), nl, */
	delete(Col, Cols, RCols), 
/*	write(trying(Row,Col)), write(diags(Diag1,Diag2)), nl, */
	diag1of(Row,Col, Max, D1), bind(Diag1, D1, Row),
/*	write(d1_is_),write(D1), nl, */
	diag2of(Row,Col, Max, D2), bind(Diag2, D2, Row),
/*	write(d2_is_),write(D2), nl, */
	N1 is Row+1, 
/*	write(safe(Row,Col)), nl, */
	ext(N1, Max, [q(Row,Col)|Selected], Diag1, Diag2, RCols, Final).

diag1of(Row, Col, Max, M) :- M is Row+Col-1.
diag2of(Row, Col, Max, M) :- M is (Row-Col)+Max.

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).

/* a pseudo-B-tree */

 createSet(Size,T) :- Size < 21, Size1 is Size+1,
				functor(T,f,Size1),
				arg(Size1,T,Size).

createSet(Size,T) :- Size > 20, functor(T,f,21),
				arg(21,T,Size),
				NewSize is Size/19,
				LastSize is Size - (NewSize*19),
				construct(T, NewSize, LastSize, 1).


construct(T, Size, Lsize, 20) :- createSet(Lsize, T1), arg(20, T, T1).

construct(T, Size, Lsize, Index) :- Index < 20,
				    createSet(Size, T1), 
				    arg(Index, T, T1),
				    Index1 is Index+1,   
				    construct(T, Size, Lsize, Index1).

bind(T,Position,Value) :- functor(T,f,Arity), Arity < 21,
					      arg(Position,T,Value).

bind(T,Position,Value) :- functor(T,f,Arity), Arity = 21,
					      arg(21, T, Size),
					      Jump is Size/19,
					      Position > (Jump*19),
					      NewPos is Position - (Jump*19),
					      arg(20,T,T1),
					      bind(T1,NewPos,Value).
								      
bind(T, Position, Value) :- functor(T,f,Arity), Arity = 21,
						arg(21, T, Size),
						Jump is Size/19,
						Position =< (Jump*19),
						Subtree is ((Position-1)/Jump)+1,
						newmod(Position, Jump, NewPos),
						arg(Subtree, T, T1),
						bind(T1, NewPos, Value).


/* newmod returns 1..N instead of 0..N-1 */

newmod(X,X,X).
newmod(X,Y,X) :- X < Y.
newmod(X,Y,Z) :- X > Y, X1 is X - Y, newmod(X1,Y,Z).

?- safe(4,Q).
