2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,7 +1,19 @@
[[File:chess_queen.jpg|400px||right]]
[[File:N_queens_problem.png|400px||right]]
Solve the [[WP:Eight_queens_puzzle|eight queens puzzle]].
You can extend the problem to solve the puzzle with a board of side NxN.
For the number of solutions for small values of N, see [http://oeis.org/A000170 oeis.org].
;Cf.
* [[Knight's tour]]
You can extend the problem to solve the puzzle with a board of size &nbsp; <big>'''N'''x'''N'''</big>.
For the number of solutions for small values of &nbsp; '''N''', &nbsp; see &nbsp; [http://oeis.org/A000170 oeis.org sequence A170].
;See also:
* &nbsp; [[Knight's tour]]
* &nbsp; [[Solve a Hidato puzzle]]
* &nbsp; [[Solve a Holy Knight's tour]]
* &nbsp; [[Solve a Numbrix puzzle]]
* &nbsp; [[Solve a Hopido puzzle]]
<br><br>

View file

@ -1,6 +1,29 @@
* N-queens problem 04/09/2015
NQUEENS PROLOG
LA R9,1 n=1
* N-QUEENS PROBLEM 04/09/2015
PRINT NOGEN
MACRO
&LAB XDECO &REG,&TARGET
&LAB B I&SYSNDX branch around work area
P&SYSNDX DS 0D,PL8 packed
W&SYSNDX DS CL13 char
I&SYSNDX CVD &REG,P&SYSNDX convert to decimal
MVC W&SYSNDX,=X'40202020202020202020212060' nice mask
EDMK W&SYSNDX,P&SYSNDX+2 edit and mark
BCTR R1,0 locate the right place
MVC 0(1,R1),W&SYSNDX+12 move the sign
MVC &TARGET.(12),W&SYSNDX move to target
MEND
PRINT NOGEN
NQUEENS CSECT
SAVE (14,12) save registers on entry
PRINT NOGEN
BALR R12,0 establish addressability
USING *,R12 set base register
ST R13,SAVEA+4 link mySA->prevSA
LA R11,SAVEA mySA
ST R11,8(R13) link prevSA->mySA
LR R13,R11 set mySA pointer
OPENEM OPEN (OUTDCB,OUTPUT) open the printer file
LA R9,1 n=1 start of loop
LOOPN CH R9,L do n=1 to l
BH ELOOPN if n>l then exit loop
SR R8,R8 m=0
@ -92,13 +115,18 @@ E90 BCTR R10,0 i=i-1
SLA R1,1 (q+r)*2
STH R0,U-2(R1) u(q+r)=0
B E60 goto e60
ZERO XDECO R9,PG+0 edit n
XDECO R8,PG+12 edit m
XPRNT PG,24 print buffer
ZERO XDECO R9,PG+0 edit N
XDECO R8,PG+12 edit M
PUT OUTDCB,PG print buffer
LA R9,1(R9) n=n+1
B LOOPN loop do n
ELOOPN EPILOG
L DC H'12' input value
ELOOPN CLOSE (OUTDCB) close output
L R13,SAVEA+4 previous save area addrs
RETURN (14,12),RC=0 return to caller with rc=0
LTORG
SAVEA DS 18F save area for chaining
OUTDCB DCB DSORG=PS,MACRF=PM,DDNAME=OUTDD use OUTDD in jcl
L DC H'13' input value
A DC H'01',H'02',H'03',H'04',H'05',H'06'
DC H'07',H'08',H'09',H'10',H'11',H'12'
U DC 46H'0'
@ -106,5 +134,5 @@ S DS 12H
Z DS H
Y DS H
PG DS CL24 buffer
YREGS
REGS make sure to incld copybook jcl
END NQUEENS

View file

@ -0,0 +1,154 @@
-- Finds all possible solutions and the unique patterns.
property Grid_Size : 8
property Patterns : {}
property Solutions : {}
property Test_Count : 0
property Rotated : {}
on run
local diff
local endTime
local msg
local rows
local startTime
set Patterns to {}
set Solutions to {}
set Rotated to {}
set Test_Count to 0
set rows to Make_Empty_List(Grid_Size)
set startTime to current date
Solve(1, rows)
set endTime to current date
set diff to endTime - startTime
set msg to ("Found " & (count Solutions) & " solutions with " & (count Patterns) & " patterns in " & diff & " seconds.") as text
display alert msg
end run
on Solve(row as integer, rows as list)
if row is greater than (count rows) then
Append_Solution(rows)
return
end if
repeat with column from 1 to Grid_Size
set Test_Count to Test_Count + 1
if Place_Queen(column, row, rows) then
Solve(row + 1, rows)
end if
end repeat
end Solve
on Place_Queen(column as integer, row as integer, rows as list)
local colDiff
local previousRow
local rowDiff
local testColumn
repeat with previousRow from 1 to (row - 1)
set testColumn to item previousRow of rows
if testColumn is equal to column then
return false
end if
set colDiff to abs (testColumn - column) as integer
set rowDiff to row - previousRow
if colDiff is equal to rowDiff then
return false
end if
end repeat
set item row of rows to column
return true
end Place_Queen
on Append_Solution(rows as list)
local column
local rowsCopy
local testReflection
local testReflectionText
local testRotation
local testRotationText
local testRotations
copy rows to rowsCopy
set end of Solutions to rowsCopy
local rowsCopy
copy rows to testRotation
set testRotations to {}
repeat 3 times
set testRotation to Rotate(testRotation)
set testRotationText to testRotation as text
if Rotated contains testRotationText then
return
end if
set end of testRotations to testRotationText
set testReflection to Reflect(testRotation)
set testReflectionText to testReflection as text
if Rotated contains testReflectionText then
return
end if
set end of testRotations to testReflectionText
end repeat
repeat with testRotationText in testRotations
set end of Rotated to (contents of testRotationText)
end repeat
set end of Rotated to (rowsCopy as text)
set end of Rotated to (Reflect(rowsCopy) as text)
set end of Patterns to rowsCopy
end Append_Solution
on Make_Empty_List(depth as integer)
local i
local emptyList
set emptyList to {}
repeat with i from 1 to depth
set end of emptyList to missing value
end repeat
return emptyList
end Make_Empty_List
on Rotate(rows as list)
local column
local newColumn
local newRow
local newRows
local row
local rowCount
set rowCount to (count rows)
set newRows to Make_Empty_List(rowCount)
repeat with row from 1 to rowCount
set column to (contents of item row of rows)
set newRow to column
set newColumn to rowCount - row + 1
set item newRow of newRows to newColumn
end repeat
return newRows
end Rotate
on Reflect(rows as list)
local column
local newRows
set newRows to {}
repeat with column in rows
set end of newRows to (count rows) - column + 1
end repeat
return newRows
end Reflect

View file

@ -1,28 +1,26 @@
defmodule RC do
def queen(n) do
add = Tuple.duplicate(true, 2*n-1)
sub = Tuple.duplicate(true, 2*n-1)
solve(n, [], add, sub)
def queen(n, display \\ true) do
solve(n, [], [], [], display)
end
def solve(n, row, _, _) when n <= length(row) do
print(n,row)
defp solve(n, row, _, _, display) when n==length(row) do
if display, do: print(n,row)
1
end
def solve(n, row, add, sub) do
defp solve(n, row, add_list, sub_list, display) do
Enum.map(Enum.to_list(0..n-1) -- row, fn x ->
iadd = x + (len = length(row))
isub = if (y = x-len) < 0, do: y + 2*n - 1, else: y
if elem(add, iadd) and elem(sub, isub) do
solve(n, [x|row], put_elem(add,iadd,false), put_elem(sub,isub,false))
else
add = x + length(row) # \ diagonal check
sub = x - length(row) # / diagonal check
if (add in add_list) or (sub in sub_list) do
0
else
solve(n, [x|row], [add | add_list], [sub | sub_list], display)
end
end) |> Enum.sum
end) |> Enum.sum # total of the solution
end
def print(n, row) do
IO.puts frame = "+-" <> String.duplicate("--", n) <> "+"
defp print(n, row) do
IO.puts frame = "+" <> String.duplicate("-", 2*n+1) <> "+"
Enum.each(row, fn x ->
line = Enum.map_join(0..n-1, fn i -> if x==i, do: "Q ", else: ". " end)
IO.puts "| #{line}|"
@ -34,3 +32,7 @@ end
Enum.each(1..6, fn n ->
IO.puts " #{n} Queen : #{RC.queen(n)}"
end)
Enum.each(7..12, fn n ->
IO.puts " #{n} Queen : #{RC.queen(n, false)}" # no display
end)

View file

@ -0,0 +1,77 @@
#!/usr/bin/env julia
__precompile__(true)
"""
# EightQueensPuzzle
Ported to **Julia** from examples in several languages from
here: https://hbfs.wordpress.com/2009/11/10/is-python-slow
"""
module EightQueensPuzzle
export main
type Board
cols::Int
nodes::Int
diag45::Int
diag135::Int
solutions::Int
Board() = new(0, 0, 0, 0, 0)
end
"Marks occupancy."
function mark!(b::Board, k::Int, j::Int)
b.cols $= (1 << j)
b.diag135 $= (1 << (j+k))
b.diag45 $= (1 << (32+j-k))
end
"Tests if a square is menaced."
function test(b::Board, k::Int, j::Int)
b.cols & (1 << j) +
b.diag135 & (1 << (j+k)) +
b.diag45 & (1 << (32+j-k)) == 0
end
"Backtracking solver."
function solve!(b::Board, niv::Int, dx::Int)
if niv > 0
for i in 0:dx-1
if test(b, niv, i) == true
mark!(b, niv, i)
solve!(b, niv-1, dx)
mark!(b, niv, i)
end
end
else
for i in 0:dx-1
if test(b, 0, i) == true
b.solutions += 1
end
end
end
b.nodes += 1
b.solutions
end
"C/C++-style `main` function."
function main()
for n = 1:17
gc()
b = Board()
@show n
print("elapsed:")
solutions = @time solve!(b, n-1, n)
@show solutions
println()
end
end
end
using EightQueensPuzzle
main()

View file

@ -0,0 +1,68 @@
juser@juliabox:~$ /opt/julia-0.5/bin/julia eight_queen_puzzle.jl
n = 1
elapsed: 0.000001 seconds
solutions = 1
n = 2
elapsed: 0.000001 seconds
solutions = 0
n = 3
elapsed: 0.000001 seconds
solutions = 0
n = 4
elapsed: 0.000001 seconds
solutions = 2
n = 5
elapsed: 0.000003 seconds
solutions = 10
n = 6
elapsed: 0.000008 seconds
solutions = 4
n = 7
elapsed: 0.000028 seconds
solutions = 40
n = 8
elapsed: 0.000108 seconds
solutions = 92
n = 9
elapsed: 0.000463 seconds
solutions = 352
n = 10
elapsed: 0.002146 seconds
solutions = 724
n = 11
elapsed: 0.010646 seconds
solutions = 2680
n = 12
elapsed: 0.057603 seconds
solutions = 14200
n = 13
elapsed: 0.334600 seconds
solutions = 73712
n = 14
elapsed: 2.055078 seconds
solutions = 365596
n = 15
elapsed: 13.480449 seconds
solutions = 2279184
n = 16
elapsed: 97.192552 seconds
solutions = 14772512
n = 17
elapsed:720.314676 seconds
solutions = 95815104

View file

@ -1,46 +1,35 @@
N = 8
board = {}
for i = 1, N do
board[i] = {}
for j = 1, N do
board[i][j] = false
end
-- We'll use nil to indicate no queen is present.
grid = {}
for i = 0, N do
grid[i] = {}
end
function Allowed( x, y )
for i = 1, x-1 do
if ( board[i][y] ) or ( i <= y and board[x-i][y-i] ) or ( y+i <= N and board[x-i][y+i] ) then
return false
end
end
return true
function can_find_solution(x0, y0)
local x0, y0 = x0 or 0, y0 or 1 -- Set default vals (0, 1).
for x = 1, x0 - 1 do
if grid[x][y0] or grid[x][y0 - x0 + x] or grid[x][y0 + x0 - x] then
return false
end
end
grid[x0][y0] = true
if x0 == N then return true end
for y0 = 1, N do
if can_find_solution(x0 + 1, y0) then return true end
end
grid[x0][y0] = nil
return false
end
function Find_Solution( x )
for y = 1, N do
if Allowed( x, y ) then
board[x][y] = true
if x == N or Find_Solution( x+1 ) then
return true
end
board[x][y] = false
end
end
return false
end
if Find_Solution( 1 ) then
for i = 1, N do
for j = 1, N do
if board[i][j] then
io.write( "|Q" )
else
io.write( "| " )
end
end
print( "|" )
if can_find_solution() then
for y = 1, N do
for x = 1, N do
-- Print "|Q" if grid[x][y] is true; "|_" otherwise.
io.write(grid[x][y] and "|Q" or "|_")
end
print("|")
end
else
print( string.format( "No solution for %d queens.\n", N ) )
print(string.format("No solution for %d queens.\n", N))
end

View file

@ -0,0 +1,78 @@
NQUEENS: PROC OPTIONS (MAIN);
DCL A(35) BIN FIXED(31) EXTERNAL;
DCL COUNT BIN FIXED(31) EXTERNAL;
COUNT = 0;
DECLARE SYSIN FILE;
DCL ABS BUILTIN;
DECLARE SYSPRINT FILE;
DECLARE N BINARY FIXED (31); /* COUNTER */
/* MAIN LOOP STARTS HERE */
GET LIST (N) FILE(SYSIN); /* N QUEENS, N X N BOARD */
PUT SKIP (1) FILE(SYSPRINT);
PUT SKIP LIST('BEGIN N QUEENS PROCESSING *****') FILE(SYSPRINT);
PUT SKIP LIST('SOLUTIONS FOR N: ',N) FILE(SYSPRINT);
PUT SKIP (1) FILE(SYSPRINT);
IF N < 4 THEN DO;
/* LESS THAN 4 MAKES NO SENSE */
PUT SKIP (2) FILE(SYSPRINT);
PUT SKIP LIST (N,' N TOO LOW') FILE (SYSPRINT);
PUT SKIP (2) FILE(SYSPRINT);
RETURN (1);
END;
IF N > 35 THEN DO;
/* WOULD TAKE WEEKS */
PUT SKIP (2) FILE(SYSPRINT);
PUT SKIP LIST (N,' N TOO HIGH') FILE (SYSPRINT);
PUT SKIP (2) FILE(SYSPRINT);
RETURN (1);
END;
CALL QUEEN(N);
PUT SKIP (2) FILE(SYSPRINT);
PUT SKIP LIST (COUNT,' SOLUTIONS FOUND') FILE(SYSPRINT);
PUT SKIP (1) FILE(SYSPRINT);
PUT SKIP LIST ('END OF PROCESSING ****') FILE(SYSPRINT);
RETURN(0);
/* MAIN LOOP ENDS ABOVE */
PLACE: PROCEDURE (PS);
DCL PS BIN FIXED(31);
DCL I BIN FIXED(31) INIT(0);
DCL A(50) BIN FIXED(31) EXTERNAL;
DO I=1 TO PS-1;
IF A(I) = A(PS) THEN RETURN(0);
IF ABS ( A(I) - A(PS) ) = (PS-I) THEN RETURN(0);
END;
RETURN (1);
END PLACE;
QUEEN: PROCEDURE (N);
DCL N BIN FIXED (31);
DCL K BIN FIXED (31);
DCL A(50) BIN FIXED(31) EXTERNAL;
DCL COUNT BIN FIXED(31) EXTERNAL;
K = 1;
A(K) = 0;
DO WHILE (K > 0);
A(K) = A(K) + 1;
DO WHILE ( ( A(K)<= N) & (PLACE(K) =0) );
A(K) = A(K) +1;
END;
IF (A(K) <= N) THEN DO;
IF (K = N ) THEN DO;
COUNT = COUNT + 1;
END;
ELSE DO;
K= K +1;
A(K) = 0;
END; /* OF INSIDE ELSE */
END; /* OF FIRST IF */
ELSE DO;
K = K -1;
END;
END; /* OF EXTERNAL WHILE LOOP */
END QUEEN;
END NQUEENS;

View file

@ -6,7 +6,7 @@ sub MAIN(\N = 8) {
}
False;
}
sub search(@field is rw, $row) {
sub search(@field, $row) {
return @field if $row == N;
for ^N -> $i {
@field[$row] = $i;

View file

@ -0,0 +1,59 @@
function PlaceQueen ( [ref]$Board, $Row, $N )
{
# For the current row, start with the first column
$Board.Value[$Row] = 0
# While haven't exhausted all columns in the current row...
While ( $Board.Value[$Row] -lt $N )
{
# If not the first row, check for conflicts
$Conflict = $Row -and
( (0..($Row-1)).Where{ $Board.Value[$_] -eq $Board.Value[$Row] }.Count -or
(0..($Row-1)).Where{ $Board.Value[$_] -eq $Board.Value[$Row] - $Row + $_ }.Count -or
(0..($Row-1)).Where{ $Board.Value[$_] -eq $Board.Value[$Row] + $Row - $_ }.Count )
# If no conflicts and the current column is a valid column...
If ( -not $Conflict -and $Board.Value[$Row] -lt $N )
{
# If this is the last row
# Board completed successfully
If ( $Row -eq ( $N - 1 ) )
{
return $True
}
# Recurse
# If all nested recursions were successful
# Board completed successfully
If ( PlaceQueen $Board ( $Row + 1 ) $N )
{
return $True
}
}
# Try the next column
$Board.Value[$Row]++
}
# Everything was tried, nothing worked
Return $False
}
function Get-NQueensBoard ( $N )
{
# Start with a default board (array of column positions for each row)
$Board = @( 0 ) * $N
# Place queens on board
# If successful...
If ( PlaceQueen -Board ([ref]$Board) -Row 0 -N $N )
{
# Convert board to strings for display
$Board | ForEach { ( @( "" ) + @(" ") * $_ + "Q" + @(" ") * ( $N - $_ ) ) -join "|" }
}
Else
{
"There is no solution for N = $N"
}
}

View file

@ -0,0 +1,7 @@
Get-NQueensBoard 8
''
Get-NQueensBoard 3
''
Get-NQueensBoard 4
''
Get-NQueensBoard 14

View file

@ -1,25 +1,25 @@
# Brute force, see the "Permutations" page for the next.perm function
safe <- function(p) {
n <- length(p)
for(i in 1:(n-1)) {
for(j in (i+1):n) {
if(abs(p[j] - p[i]) == abs(j - i)) return(FALSE)
}
}
return(TRUE)
n <- length(p)
for (i in seq(1, n - 1)) {
for (j in seq(i + 1, n)) {
if (abs(p[j] - p[i]) == abs(j - i)) return(F)
}
}
return(T)
}
queens <- function(n) {
p <- 1:n
k <- 0
while(!is.null(p)) {
if(safe(p)) {
cat(p,"\n")
k <- k + 1
}
p <- next.perm(p)
}
return(k)
p <- 1:n
k <- 0
while (!is.null(p)) {
if(safe(p)) {
cat(p, "\n")
k <- k + 1
}
p <- next.perm(p)
}
return(k)
}
queens(8)

View file

@ -1,51 +1,49 @@
/*REXX program places N queens on a NxN chessboard; the 8 queens problem*/
parse arg N . /*get board size arg (if any). */
if N=='' then N=8; if N<1 then call noSol /*No arg? Use the default.*/
rank=1; file=1; q=0 /*starting rank & file; # queens.*/
@.=0; !=left('', 9* (N<18)) /*define empty board, indentation*/
/*═════════════════════════════════════find solution: N queens problem.*/
do while q<N; @.file.rank=1 /*keep placing queens until done.*/
if safe?(file,rank) then do; q=q+1 /*if not being attacked, eureka! */
file=1 /*another attempt at another file*/
rank=rank+1 /*and also bump the rank pointer.*/
iterate /*go&try another queen placement.*/
end /* [↑] found a good Q placement.*/
@.file.rank=0 /*not safe, so remove this queen.*/
file=file+1 /*So, try the next (higher) file.*/
do while file>N; rank=rank-1; if rank==0 then call noSol
do j=1 for N; if \@.j.rank then iterate /*occupied?*/
file=j; @.file.rank=0; q=q-1; file=j+1; leave /*j*/
/*REXX program places N queens on an NxN chessboard (the eight queens problem). */
parse arg N . /*obtain optional argument from the CL.*/
if N=='' | N=="," then N=8 /*Not specified: Then use the default.*/
if N<1 then call noSol /*display a message, the board is bad. */
rank=1; file=1; #=0 /*starting rank&file; #≡number queens.*/
@.=0; pad=left('', 9* (N<18)) /*define empty board; set indentation.*/
do while #<N; @.file.rank=1 /*keep placing queens until we're done.*/
if ok(file,rank) then do; #=#+1 /*Queen not being attacked? Then eureka*/
file=1 /*use another attempt at another file. */
rank=rank+1 /*and also bump the rank counter. */
iterate /*go and try another queen placement. */
end /* [↑] found a good queen placement. */
@.file.rank=0 /*It isn't safe. So remove this queen.*/
file=file+1 /*So, try the next (higher) file. */
do while file>N; rank=rank-1; if rank==0 then call noSol
do j=1 for N; if \@.j.rank then iterate /*occupied?*/
file=j; @.file.rank=0; #=#-1; file=j+1; leave /*j*/
end /*j*/
end /*while file>N*/
end /*while q<N*/
/*══════════════════════════════════════show chessboard with a solution.*/
say 'A solution for' N "queens:"; _ = substr( copies("┼───", N) ,2)
lineT = ''_""; say; say ! translate(lineT,'',"")
lineB = ''_""; lineB = translate(lineB, '', "")
line = ''_"" /*define a line for cell boundry.*/
bar = '' /*kinds: horizonal/vertical/salad*/
if 1=='f1'x then do; queenSymbol='Q'; dither='9c'x; end /*for EBCDIC.*/
else do; queenSymbol=''; dither='b0'x; end /* " ASCII.*/
Bqueen = dither||queenSymbol||dither /*glyph befitting the black queen*/
Wqueen = ' 'queenSymbol" " /* " " " white " */
/*═══════════════════════════════════════show chessboard with the queens*/
do r=1 for N; if r\==1 then say ! line; _= /*process the rank &*/
do f=1 for N; black=(f+r)//2 /*the file; is it a black square?*/
Qgylph=Wqueen; if black then Qgylph=Bqueen /*use a black queen.*/
/*is it black sqare?*/
if @.f.r then _=_ || bar || Qgylph /*use the 3-char symbol for queen*/
else if black then _=_||bar||copies(dither,3) /*dithering.*/
else _=_||bar' ' /*3 blanks. */
end /*f*/ /* [↑] preserve square chessboard*/
say ! _ || bar /*show a rank of the chessboard. */
end /*r*/ /*80 cols can view 19x19 chessbrd*/
say ! lineB; say /*show last line, + a blank line.*/
exit 1 /*stick a fork in it, we're done.*/
/*──────────────────────────────────NOSOL subroutine────────────────────*/
noSol: say "No solution for" N 'queens.'; exit 0
/*──────────────────────────────────SAFE? subroutine────────────────────*/
safe?: procedure expose @. N; parse arg f,r; rm=r-1; fm=f-1; fp=f+1
do k=1 for rm; if @.f.k then return 0; end
f=fm; do k=rm by -1 for rm while f\==0; if @.f.k then return 0; f=f-1; end
f=fp; do k=rm by -1 for rm while f <=N; if @.f.k then return 0; f=f+1; end
return 1
end /*while #<N*/
say 'A solution for' N "queens:"; a = substr( copies("┼───", N) ,2); say
say pad translate(''a"", '', "") /*display the top rank (of the board).*/
line = ''a""; dither='' /*define a line (bar) for cell boundry.*/
bar = '' ; queen='Q' /*kinds: horizontal, vertical, salad. */
Bqueen = dither || queen || dither /*glyph befitting a black-square queen.*/
Wqueen = ' 'queen" " /* " " " white-square " */
do rank=1 for N; if rank\==1 then say pad line; _= /*display sep for rank.*/
do file=1 for N; B=(file+rank)//2 /*is the square black? */
Qgylph=Wqueen; if B then Qgylph=Bqueen /*use a dithered queen.*/
if @.file.rank then _=_ || bar || Qgylph /*3-char queen symbol. */
else if B then _=_ || bar || copies(dither,3) /*use dithering for sq.*/
else _=_ || bar || copies(' ' ,3) /* " 3 blanks " " */
end /*file*/ /* [↑] preserve square-ish chessboard.*/
say pad _ || bar /*show a single rank of the chessboard.*/
end /*rank*/ /*80 cols can view a 19x19 chessboard.*/
say pad translate(''a"", '', "") /*display the last rank (of the board).*/
exit 1 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
noSol: say; say "No solution for" N 'queens.'; say; exit 0
/*──────────────────────────────────────────────────────────────────────────────────────*/
ok: parse arg f,r; rm=r-1; fm=f-1; fp=f+1
do k=1 for rm; if @.f.k then return 0; end
f=fm; do k=rm by -1 for rm while f\==0; if @.f.k then return 0; f=f-1; end
f=fp; do k=rm by -1 for rm while f <=N; if @.f.k then return 0; f=f+1; end
return 1 /* ↑↑↑↑↑↑↑↑ is queen under attack?*/

View file

@ -1,20 +1,19 @@
class Queen
def initialize(num=8)
@num = num
end
attr_reader :count
def solve(out=true)
def initialize(num=8, out=true)
@num = num
@out = out
@row = *0...@num
@frame = "+-" + "--" * @num + "+"
@count = 0
add = Array.new(2 * @num - 1, true)
sub = Array.new(2 * @num - 1, true)
_solve([], add, sub)
@count
add = Array.new(2 * @num - 1, true) # \ direction check
sub = Array.new(2 * @num - 1, true) # / direction check
solve([], add, sub)
end
def _solve(row, add, sub)
private
def solve(row, add, sub)
y = row.size
if y == @num
print_out(row) if @out
@ -23,7 +22,7 @@ class Queen
(@row-row).each do |x|
next unless add[x+y] and sub[x-y]
add[x+y] = sub[x-y] = false
_solve(row+[x], add, sub)
solve(row+[x], add, sub)
add[x+y] = sub[x-y] = true
end
end

View file

@ -1,9 +1,9 @@
(1..6).each do |n|
puzzle = Queen.new(n)
puts " #{n} Queen : #{puzzle.solve}"
puts " #{n} Queen : #{puzzle.count}"
end
(7..12).each do |n|
puzzle = Queen.new(n)
puts " #{n} Queen : #{puzzle.solve(false)}" # no display
puzzle = Queen.new(n, false) # do not display
puts " #{n} Queen : #{puzzle.count}"
end

View file

@ -0,0 +1,77 @@
use std::collections::LinkedList;
use std::iter::IntoIterator;
fn main() {
for (n, s) in NQueens::new(8).enumerate() {
println!("Solution #{}:\n{}\n", n + 1, s.to_string());
}
}
fn permutations<'a, T, I>(collection: I) -> Box<Iterator<Item=LinkedList<T>> + 'a>
where I: 'a + IntoIterator<Item=T> + Clone,
T: 'a + PartialEq + Copy + Clone {
if collection.clone().into_iter().count() == 0 {
Box::new(vec![LinkedList::new()].into_iter())
}
else {
Box::new(
collection.clone().into_iter().flat_map(move |i| {
permutations(collection.clone().into_iter()
.filter(move |&i0| i != i0)
.collect::<Vec<_>>())
.map(move |mut l| {l.push_front(i); l})
})
)
}
}
pub struct NQueens {
iterator: Box<Iterator<Item=NQueensSolution>>
}
impl NQueens {
pub fn new(n: u32) -> NQueens {
NQueens {
iterator: Box::new(permutations(0..n)
.filter(|vec| {
let iter = vec.iter().enumerate();
iter.clone().all(|(col, &row)| {
iter.clone().filter(|&(c,_)| c != col)
.all(|(ocol, &orow)| {
col as i32 - row as i32 !=
ocol as i32 - orow as i32 &&
col as u32 + row != ocol as u32 + orow
})
})
})
.map(|vec| NQueensSolution(vec))
)
}
}
}
impl Iterator for NQueens {
type Item = NQueensSolution;
fn next(&mut self) -> Option<NQueensSolution> {
self.iterator.next()
}
}
pub struct NQueensSolution(LinkedList<u32>);
impl ToString for NQueensSolution {
fn to_string(&self) -> String {
let mut str = String::new();
for &row in self.0.iter() {
for r in 0..self.0.len() as u32 {
if r == row {
str.push_str("Q ");
} else {
str.push_str("- ");
}
}
str.push('\n');
}
str
}
}

View file

@ -14,7 +14,3 @@ def expand(solutions: Iterator[List[Pos]], size: Int, row: Int) =
pos <- rowSet(size, row)
if solution forall (_ legal pos)
} yield pos :: solution
def seed(size: Int) = rowSet(size, 0) map (sol => List(sol))
def solve(size: Int) = (1 until size).foldLeft(seed(size)) (expand(_, size, _))

View file

@ -0,0 +1,18 @@
def vecOk(v: IndexedSeq[Int])(f: (Int,Int) => Int): Boolean = {
def vecOkIter(level: Int)(lst: List[Int]): Boolean = {
if (level > -1) {
val d = f(v(level),level)
if (lst.contains(d)) false
else vecOkIter(level-1)(d :: lst)
}
else true
}
vecOkIter(v.length-1)(List[Int]())
}
def nQueen(n: Int) = for (
v <- (1 to n).permutations
if vecOk(v)(_+_) && vecOk(v)(_-_)
) yield v
nQueen(8)