:- lib(ic).
%%%%%%%%%%%%%%%%%%%%%%% Ex 1.4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% StrategyName may be bf for brute force, otherwise the constraint strategy applies
nqueens(N,StrategyName) :-
(StrategyName == bf ->
Strategy = nqueensBruteForce(N,Sol)
;
Strategy = nqueensConstraints(N,Sol)
),
% puts all solutions to our problem in List
findall(Sol,call(Strategy),List),
% some output
showSolutions(List),
length(List,Length),
printf("found solutions: %w%n",[Length]).
nqueensConstraints(N,Sol) :-
init(N,Sol),
% constrains the variables
constraints(Sol),
% finds a valid instantiation
labeling(Sol).
nqueensBruteForce(N,Sol) :-
init(N,Sol),
% tries a possible variable instantiation
labeling(Sol),
% dismisses the instantiation if it does not fulfil the constraints
constraints(Sol).
init(N,Sol) :-
% instantiates Sol to a list of N variable elements
length(Sol,N),
% each element of list Sol can range from 1 to N
Sol #:: [1..N].
% given a list of variables [X1,...Xn], this predicate puts the N-Queens constraints:
% (for all Xi and Xj) Xi \= Xj, Xi-Xj \= i-j, Xi-Xj \= j-i
constraints([]).
constraints([H|T]) :-
different(H,T,1),
constraints(T).
different(_,[],_).
different(Xi,[Xj|T],Diff) :-
Xi #\= Xj,
Xi-Xj #\= Diff,
Xi-Xj #\= -Diff,
Diff1 is Diff+1,
different(Xi,T,Diff1).
showSolutions([]).
showSolutions([H|T]) :-
writeln(H),
showSolutions(T).