There is an elegant solution to n-queens problem in Prolog:
queens(N, Queens) :-
length(Queens, N),
place_queens(N, Queens, _, _).
place_queens(0, _, _, _) :- !.
place_queens(N, Cs, Us, [_|Ds]) :-
M is N - 1,
place_queens(M, Cs, [_|Us], Ds),
place_queen(N, Cs, Us, Ds).
place_queen(N, [N|_], [N|_], [N|_]).
place_queen(N, [_|Cs], [_|Us], [_|Ds]) :-
place_queen(N, Cs, Us, Ds).
All 92 solutions can be collected with:
?- findall(Queens, queens(8, Queens), Res).
The same thing implemented in Shen may look like:
(defprolog queens
N Queens <--
(len Queens N)
(place_queens N Queens _ _);)
(defprolog place_queens
0 _ _ _ <-- !;
N Cs Us [_|Ds] <--
(is M (- N 1))
(place_queens M Cs [_|Us] Ds)
(place_queen N Cs Us Ds);)
(defprolog place_queen
N [N| _] [N| _] [N| _] <-- ;
N [_|Cs] [_|Us] [_|Ds] <-- (place_queen N Cs Us Ds);)
(defprolog len
[] 0 <-- ;
[_|L] N <-- (len L M) (is N (+ 1 M));)
And it works well when queried for a single solution:
(prolog? (queens 8 Queens) (return Queens))
[1 7 5 8 2 4 6 3]
However, it fails with findall:
(prolog? (findall Queens (queens 8 Queens) Res) (return Res))
Invalid index 10000 for (SIMPLE-VECTOR 10000), should be a non-negative integer below 10000.
(prolog? (findall Queens (queens 8 Queens) Res) (len Res N) (return N))
Invalid index 10000 for (SIMPLE-VECTOR 10000), should be a non-negative integer below 10000.
Tested with kernel S33.1.2 under shen-scheme and with kernel S34.1 under SBCL.
Is this a bug or some subtle difference between Shen and Prolog?
Cheers,
Leszek