Time for an 2014 update…
This commit is contained in:
parent
372c577f83
commit
09687c4926
2520 changed files with 34227 additions and 7318 deletions
|
|
@ -1,44 +1,9 @@
|
|||
import std.stdio;
|
||||
|
||||
enum int SIDE = 8;
|
||||
int[SIDE] board;
|
||||
|
||||
bool unsafe(in int y) nothrow {
|
||||
immutable int x = board[y];
|
||||
foreach (i; 1 .. y + 1) {
|
||||
int t = board[y - i];
|
||||
if ((t == x) || (t == x - i) || (t == x + i))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void showBoard() {
|
||||
static int s = 1;
|
||||
writeln("\nSolution #", s++);
|
||||
foreach (y; 0 .. SIDE) {
|
||||
foreach (x; 0 .. SIDE)
|
||||
write(board[y] == x ? '*' : '.');
|
||||
writeln();
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
int y = 0;
|
||||
board[0] = -1;
|
||||
import std.stdio, std.algorithm, std.range, permutations2;
|
||||
|
||||
while (y >= 0) {
|
||||
do {
|
||||
board[y]++;
|
||||
} while (board[y] < SIDE && unsafe(y));
|
||||
|
||||
if (board[y] < SIDE) {
|
||||
if (y < (SIDE - 1))
|
||||
board[++y] = -1;
|
||||
else
|
||||
showBoard();
|
||||
} else
|
||||
y--;
|
||||
}
|
||||
enum n = 8;
|
||||
n.iota.array.permutations.filter!(p =>
|
||||
n.iota.map!(i => p[i] + i).array.sort().uniq.count == n &&
|
||||
n.iota.map!(i => p[i] - i).array.sort().uniq.count == n)
|
||||
.count.writeln;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,90 +1,44 @@
|
|||
import std.stdio, std.conv;
|
||||
enum side = 8;
|
||||
__gshared int[side] board;
|
||||
|
||||
ulong nQueens(in uint nn) pure nothrow
|
||||
in {
|
||||
assert(nn > 0 && nn <= 27,
|
||||
"'side' value must be in 1 .. 27.");
|
||||
} body {
|
||||
if (nn < 4)
|
||||
return nn == 1;
|
||||
|
||||
enum uint ulen = uint.sizeof * 8;
|
||||
immutable uint full = uint.max - ((1 << (ulen - nn)) - 1);
|
||||
immutable n = nn - 3;
|
||||
|
||||
typeof(return) count;
|
||||
uint[32] l=void, r=void, c=void;
|
||||
uint[33] mm; // mm and mmi are a stack.
|
||||
|
||||
// Require second queen to be left of the first queen, so
|
||||
// we ever only test half of the possible solutions. This
|
||||
// is why we can't handle n=1 here.
|
||||
for (uint b0 = 1U << (ulen - n - 3); b0; b0 <<= 1) {
|
||||
for (uint b1 = b0 << 2; b1; b1 <<= 1) {
|
||||
uint d = n;
|
||||
// c: columns occupied by previous queens.
|
||||
c[n] = b0 | b1;
|
||||
// l: columns attacked by left diagonals.
|
||||
l[n] = (b0 << 2) | (b1 << 1);
|
||||
// r: by right diagnoals.
|
||||
r[n] = (b0 >> 2) | (b1 >> 1);
|
||||
|
||||
// Availabe columns on current row.
|
||||
uint bits = full & ~(l[n] | r[n] | c[n]);
|
||||
|
||||
uint mmi = 1;
|
||||
mm[mmi] = bits;
|
||||
|
||||
while (bits) {
|
||||
// d: depth, aka row. counting backwards.
|
||||
// Because !d is often faster than d != n.
|
||||
while (d) {
|
||||
// immutable uint pos = 1U << bits.bsf; // Slower.
|
||||
immutable uint pos = -(cast(int)bits) & bits;
|
||||
|
||||
// Mark bit used. Only put current bits on
|
||||
// stack if not zero, so backtracking will
|
||||
// skip exhausted rows (because reading stack
|
||||
// variable is slow compared to registers).
|
||||
bits &= ~pos;
|
||||
if (bits) {
|
||||
mm[mmi] = bits | d;
|
||||
mmi++;
|
||||
}
|
||||
|
||||
d--;
|
||||
l[d] = (l[d + 1] | pos) << 1;
|
||||
r[d] = (r[d + 1] | pos) >> 1;
|
||||
c[d] = c[d + 1] | pos;
|
||||
|
||||
bits = full & ~(l[d] | r[d] | c[d]);
|
||||
|
||||
if (!bits)
|
||||
break;
|
||||
if (!d) {
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom of stack m is a zero'd field acting as
|
||||
// sentinel. When saving to stack, left 27 bits
|
||||
// are the available columns, while right 5 bits
|
||||
// is the depth. Hence solution is limited to size
|
||||
// 27 board -- not that it matters in foreseeable
|
||||
// future.
|
||||
mmi--;
|
||||
bits = mm[mmi];
|
||||
d = bits & 31U;
|
||||
bits &= ~31U;
|
||||
}
|
||||
}
|
||||
bool isUnsafe(in int y) nothrow {
|
||||
immutable int x = board[y];
|
||||
foreach (immutable i; 1 .. y + 1) {
|
||||
immutable int t = board[y - i];
|
||||
if (t == x || t == x - i || t == x + i)
|
||||
return true;
|
||||
}
|
||||
|
||||
return count * 2;
|
||||
return false;
|
||||
}
|
||||
|
||||
void main(in string[] args) {
|
||||
immutable uint side = (args.length >= 2) ? args[1].to!uint : 8;
|
||||
writefln("N-queens(%d) = %d solutions.", side, side.nQueens);
|
||||
void showBoard() nothrow {
|
||||
import core.stdc.stdio;
|
||||
|
||||
static int s = 1;
|
||||
printf("\nSolution #%d:\n", s++);
|
||||
foreach (immutable y; 0 .. side) {
|
||||
foreach (immutable x; 0 .. side)
|
||||
putchar(board[y] == x ? 'Q' : '.');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void main() nothrow {
|
||||
int y = 0;
|
||||
board[0] = -1;
|
||||
|
||||
while (y >= 0) {
|
||||
do {
|
||||
board[y]++;
|
||||
} while (board[y] < side && y.isUnsafe);
|
||||
|
||||
if (board[y] < side) {
|
||||
if (y < (side - 1))
|
||||
board[++y] = -1;
|
||||
else
|
||||
showBoard;
|
||||
} else
|
||||
y--;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
90
Task/N-queens-problem/D/n-queens-problem-3.d
Normal file
90
Task/N-queens-problem/D/n-queens-problem-3.d
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import std.stdio, std.conv;
|
||||
|
||||
ulong nQueens(in uint nn) pure nothrow
|
||||
in {
|
||||
assert(nn > 0 && nn <= 27,
|
||||
"'side' value must be in 1 .. 27.");
|
||||
} body {
|
||||
if (nn < 4)
|
||||
return nn == 1;
|
||||
|
||||
enum uint ulen = uint.sizeof * 8;
|
||||
immutable uint full = uint.max - ((1 << (ulen - nn)) - 1);
|
||||
immutable n = nn - 3;
|
||||
|
||||
typeof(return) count;
|
||||
uint[32] l=void, r=void, c=void;
|
||||
uint[33] mm; // mm and mmi are a stack.
|
||||
|
||||
// Require second queen to be left of the first queen, so
|
||||
// we ever only test half of the possible solutions. This
|
||||
// is why we can't handle n=1 here.
|
||||
for (uint b0 = 1U << (ulen - n - 3); b0; b0 <<= 1) {
|
||||
for (uint b1 = b0 << 2; b1; b1 <<= 1) {
|
||||
uint d = n;
|
||||
// c: columns occupied by previous queens.
|
||||
c[n] = b0 | b1;
|
||||
// l: columns attacked by left diagonals.
|
||||
l[n] = (b0 << 2) | (b1 << 1);
|
||||
// r: by right diagnoals.
|
||||
r[n] = (b0 >> 2) | (b1 >> 1);
|
||||
|
||||
// Availabe columns on current row.
|
||||
uint bits = full & ~(l[n] | r[n] | c[n]);
|
||||
|
||||
uint mmi = 1;
|
||||
mm[mmi] = bits;
|
||||
|
||||
while (bits) {
|
||||
// d: depth, aka row. counting backwards.
|
||||
// Because !d is often faster than d != n.
|
||||
while (d) {
|
||||
// immutable uint pos = 1U << bits.bsf; // Slower.
|
||||
immutable uint pos = -(cast(int)bits) & bits;
|
||||
|
||||
// Mark bit used. Only put current bits on
|
||||
// stack if not zero, so backtracking will
|
||||
// skip exhausted rows (because reading stack
|
||||
// variable is slow compared to registers).
|
||||
bits &= ~pos;
|
||||
if (bits) {
|
||||
mm[mmi] = bits | d;
|
||||
mmi++;
|
||||
}
|
||||
|
||||
d--;
|
||||
l[d] = (l[d + 1] | pos) << 1;
|
||||
r[d] = (r[d + 1] | pos) >> 1;
|
||||
c[d] = c[d + 1] | pos;
|
||||
|
||||
bits = full & ~(l[d] | r[d] | c[d]);
|
||||
|
||||
if (!bits)
|
||||
break;
|
||||
if (!d) {
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom of stack m is a zero'd field acting as
|
||||
// sentinel. When saving to stack, left 27 bits
|
||||
// are the available columns, while right 5 bits
|
||||
// is the depth. Hence solution is limited to size
|
||||
// 27 board -- not that it matters in foreseeable
|
||||
// future.
|
||||
mmi--;
|
||||
bits = mm[mmi];
|
||||
d = bits & 31U;
|
||||
bits &= ~31U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count * 2;
|
||||
}
|
||||
|
||||
void main(in string[] args) {
|
||||
immutable uint side = (args.length >= 2) ? args[1].to!uint : 8;
|
||||
writefln("N-queens(%d) = %d solutions.", side, side.nQueens);
|
||||
}
|
||||
83
Task/N-queens-problem/Erlang/n-queens-problem.erl
Normal file
83
Task/N-queens-problem/Erlang/n-queens-problem.erl
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
-module( n_queens ).
|
||||
|
||||
-export( [display/1, solve/1, task/0] ).
|
||||
|
||||
display( Board ) ->
|
||||
%% Queens are in the positions in the Board list.
|
||||
%% Top left corner is {1, 1}, Bottom right is {N, N}. There is a queen in the max column.
|
||||
N = lists:max( [X || {X, _Y} <- Board] ),
|
||||
[display_row(Y, N, Board) || Y <- lists:seq(1, N)].
|
||||
|
||||
solve( N ) ->
|
||||
Positions = [{X, Y} || X <- lists:seq(1, N), Y <- lists:seq(1, N)],
|
||||
try
|
||||
bt( N, Positions, [] )
|
||||
|
||||
catch
|
||||
_:{ok, Board} -> Board
|
||||
|
||||
end.
|
||||
|
||||
task() ->
|
||||
task( 4 ),
|
||||
task( 8 ).
|
||||
|
||||
|
||||
|
||||
bt( N, Positions, Board ) -> bt_reject( is_not_allowed_queen_placement(N, Board), N, Positions, Board ).
|
||||
|
||||
bt_accept( true, _N, _Positions, Board ) -> erlang:throw( {ok, Board} );
|
||||
bt_accept( false, N, Positions, Board ) -> bt_loop( N, Positions, [], Board ).
|
||||
|
||||
bt_loop( _N, [], _Rejects, _Board ) -> failed;
|
||||
bt_loop( N, [Position | T], Rejects, Board ) ->
|
||||
bt( N, T ++ Rejects, [Position | Board] ),
|
||||
bt_loop( N, T, [Position | Rejects], Board ).
|
||||
|
||||
bt_reject( true, _N, _Positions, _Board ) -> backtrack;
|
||||
bt_reject( false, N, Positions, Board ) -> bt_accept( is_all_queens(N, Board), N, Positions, Board ).
|
||||
|
||||
diagonals( N, {X, Y} ) ->
|
||||
D1 = diagonals( N, X + 1, fun diagonals_add1/1, Y + 1, fun diagonals_add1/1 ),
|
||||
D2 = diagonals( N, X + 1, fun diagonals_add1/1, Y - 1, fun diagonals_subtract1/1 ),
|
||||
D3 = diagonals( N, X - 1, fun diagonals_subtract1/1, Y + 1, fun diagonals_add1/1 ),
|
||||
D4 = diagonals( N, X - 1, fun diagonals_subtract1/1, Y - 1, fun diagonals_subtract1/1 ),
|
||||
D1 ++ D2 ++ D3 ++ D4.
|
||||
|
||||
diagonals( _N, 0, _Change_x, _Y, _Change_y ) -> [];
|
||||
diagonals( _N, _X, _Change_x, 0, _Change_y ) -> [];
|
||||
diagonals( N, X, _Change_x, _Y, _Change_y ) when X > N -> [];
|
||||
diagonals( N, _X, _Change_x, Y, _Change_y ) when Y > N -> [];
|
||||
diagonals( N, X, Change_x, Y, Change_y ) -> [{X, Y} | diagonals( N, Change_x(X), Change_x, Change_y(Y), Change_y )].
|
||||
|
||||
diagonals_add1( N ) -> N + 1.
|
||||
|
||||
diagonals_subtract1( N ) -> N - 1.
|
||||
|
||||
display_row( Row, N, Board ) ->
|
||||
[io:fwrite("~s", [display_queen(X, Row, Board)]) || X <- lists:seq(1, N)],
|
||||
io:nl().
|
||||
|
||||
display_queen( X, Y, Board ) -> display_queen( lists:member({X, Y}, Board) ).
|
||||
display_queen( true ) -> " Q";
|
||||
display_queen( false ) -> " .".
|
||||
|
||||
is_all_queens( N, Board ) -> N =:= erlang:length( Board ).
|
||||
|
||||
is_diagonal( _N, [] ) -> false;
|
||||
is_diagonal( N, [Position | T] ) ->
|
||||
Diagonals = diagonals( N, Position ),
|
||||
T =/= (T -- Diagonals)
|
||||
orelse is_diagonal( N, T ).
|
||||
|
||||
is_not_allowed_queen_placement( N, Board ) ->
|
||||
Pieces = erlang:length( Board ),
|
||||
{Xs, Ys} = lists:unzip( Board ),
|
||||
Pieces =/= erlang:length( lists:usort(Xs) )
|
||||
orelse Pieces =/= erlang:length( lists:usort(Ys) )
|
||||
orelse is_diagonal( N, Board ).
|
||||
|
||||
task( N ) ->
|
||||
io:fwrite( "N = ~p. One solution.~n", [N] ),
|
||||
Board = solve( N ),
|
||||
display( Board ).
|
||||
37
Task/N-queens-problem/GAP/n-queens-problem.gap
Normal file
37
Task/N-queens-problem/GAP/n-queens-problem.gap
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Quick and dirty solution, checking all permutations without backtracking (thus it's slow)
|
||||
IsSafe := function(a)
|
||||
local n, i, j;
|
||||
n := Length(a);
|
||||
for i in [1 .. n - 1] do
|
||||
for j in [i + 1 .. n] do
|
||||
if AbsInt(a[j] - a[i]) = j - i then
|
||||
return false;
|
||||
fi;
|
||||
od;
|
||||
od;
|
||||
return true;
|
||||
end;
|
||||
|
||||
Queens := function(n)
|
||||
local p, a, v;
|
||||
v := [];
|
||||
for p in SymmetricGroup(n) do
|
||||
a := List([1 .. n], i -> i^p);
|
||||
if IsSafe(a) then
|
||||
Add(v, a);
|
||||
fi;
|
||||
od;
|
||||
return v;
|
||||
end;
|
||||
|
||||
v := Queens(8);;
|
||||
Length(v);
|
||||
PrintArray(PermutationMat(PermListList([1 .. 8], v[1]), 8));
|
||||
[ [ 0, 0, 1, 0, 0, 0, 0, 0 ],
|
||||
[ 0, 0, 0, 0, 0, 1, 0, 0 ],
|
||||
[ 0, 1, 0, 0, 0, 0, 0, 0 ],
|
||||
[ 0, 0, 0, 0, 1, 0, 0, 0 ],
|
||||
[ 0, 0, 0, 0, 0, 0, 0, 1 ],
|
||||
[ 1, 0, 0, 0, 0, 0, 0, 0 ],
|
||||
[ 0, 0, 0, 0, 0, 0, 1, 0 ],
|
||||
[ 0, 0, 0, 1, 0, 0, 0, 0 ] ]
|
||||
12
Task/N-queens-problem/Haskell/n-queens-problem-3.hs
Normal file
12
Task/N-queens-problem/Haskell/n-queens-problem-3.hs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import Data.List (nub, permutations)
|
||||
|
||||
-- checks if queens are on the same diagonal
|
||||
-- with [0..] we place each queen on her own row
|
||||
check f = length . nub . zipWith f [0..]
|
||||
|
||||
-- filters out results where 2 or more queens are on the same diagonal
|
||||
-- with [0..n-1] we place each queeen on her own column
|
||||
generate n = filter (\x -> check (+) x == n && check (-) x == n) $ permutations [0..n-1]
|
||||
|
||||
-- 8 is for "8 queens"
|
||||
main = print $ generate 8
|
||||
84
Task/N-queens-problem/Liberty-BASIC/n-queens-problem.liberty
Normal file
84
Task/N-queens-problem/Liberty-BASIC/n-queens-problem.liberty
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
'N queens
|
||||
'>10 would not work due to way permutations used
|
||||
'anyway, 10 doesn't fit in memory
|
||||
Input "Input N for N queens puzzle (4..9) ";N
|
||||
if N<4 or N>9 then print "N out of range - quitting": end
|
||||
|
||||
ABC$= " "
|
||||
dash$ = ""
|
||||
for i = 0 to N-1
|
||||
ABC$=ABC$+" "+chr$(asc("a")+i)
|
||||
dash$ = dash$+"--"
|
||||
next
|
||||
|
||||
dim q(N)
|
||||
t0=time$("ms")
|
||||
|
||||
fact = 1
|
||||
for i = 1 to N
|
||||
fact = fact*i
|
||||
next
|
||||
|
||||
dim anagram$(fact)
|
||||
global nPerms
|
||||
print "Filling permutations array"
|
||||
t0=time$("ms")
|
||||
res$=permutation$("", left$("0123456789", N))
|
||||
t1=time$("ms")
|
||||
print "Created all possible permutations ";t1-t0
|
||||
|
||||
t0=time$("ms")
|
||||
'actually fact = nPerms
|
||||
for k=1 to nPerms
|
||||
for i=0 to N-1
|
||||
q(i)=val(mid$(anagram$(k),i+1,1))
|
||||
'print q(i);
|
||||
next
|
||||
'print
|
||||
|
||||
fail = 0
|
||||
for i=0 to N-1
|
||||
for j=i+1 to N-1
|
||||
'check rows are different
|
||||
if q(i)=q(j) then fail = 1: exit for
|
||||
'check diagonals are different
|
||||
if i+q(i)=j+q(j) then fail = 1: exit for
|
||||
'check other diagonals are different
|
||||
if i-q(i)=j-q(j) then fail = 1: exit for
|
||||
next
|
||||
if fail then exit for
|
||||
next
|
||||
|
||||
if not(fail) then
|
||||
num=num+1
|
||||
print " ";dash$
|
||||
for i=0 to N-1
|
||||
print N-i; space$(2*q(i));" *"
|
||||
next
|
||||
print " ";dash$
|
||||
print ABC$
|
||||
end if
|
||||
|
||||
next
|
||||
|
||||
t1=time$("ms")
|
||||
print "Time taken ";t1-t0
|
||||
print "Number of solutions ";num
|
||||
|
||||
'----------------------------------
|
||||
'from
|
||||
'http://babek.info/libertybasicfiles/lbnews/nl124/wordgames.htm
|
||||
'Programming a Word Game by Janet Terra,
|
||||
'The Liberty Basic Newsletter - Issue #124 - September 2004
|
||||
Function permutation$(pre$, post$)
|
||||
'Note the variable nPerms must first be stated as a global variable.
|
||||
lgth = Len(post$)
|
||||
If lgth < 2 Then
|
||||
nPerms = nPerms + 1
|
||||
anagram$(nPerms) = pre$;post$
|
||||
Else
|
||||
For i = 1 To lgth
|
||||
tmp$=permutation$(pre$+Mid$(post$,i,1),Left$(post$,i-1)+Right$(post$,lgth-i))
|
||||
Next i
|
||||
End If
|
||||
End Function
|
||||
Loading…
Add table
Add a link
Reference in a new issue