%% nqueens — permutation-and-test formulation.
%% Caller passes the row list [1..N]; queens/2 finds N column placements
%% s.t. no two queens attack on a diagonal. Same-column attacks are
%% structurally impossible — Qs is a permutation, all distinct.
%%
%% No `>/2` `</2` `=</2` built-ins yet, so range/3 is omitted; tests pass
%; the literal range list. Once the operator table lands and arithmetic
%% comparison built-ins are in, range/3 can be added.
queens(L, Qs) :- permute(L, Qs), safe(Qs).

permute([], []).
permute(L, [H|T]) :- select(H, L, R), permute(R, T).

select(X, [X|T], T).
select(X, [H|T], [H|R]) :- select(X, T, R).

safe([]).
safe([Q|Qs]) :- safe(Qs), no_attack(Q, Qs, 1).

no_attack(_, [], _).
no_attack(Q, [Q1|Qs], D) :-
  is(D2, +(Q, D)),
  \=(D2, Q1),
  is(D3, -(Q, D)),
  \=(D3, Q1),
  is(D1, +(D, 1)),
  no_attack(Q, Qs, D1).
