2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -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 <big>'''N'''x'''N'''</big>.
|
||||
|
||||
For the number of solutions for small values of '''N''', see [http://oeis.org/A000170 oeis.org sequence A170].
|
||||
|
||||
|
||||
;See also:
|
||||
* [[Knight's tour]]
|
||||
* [[Solve a Hidato puzzle]]
|
||||
* [[Solve a Holy Knight's tour]]
|
||||
* [[Solve a Numbrix puzzle]]
|
||||
* [[Solve a Hopido puzzle]]
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -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 ®,&TARGET
|
||||
&LAB B I&SYSNDX branch around work area
|
||||
P&SYSNDX DS 0D,PL8 packed
|
||||
W&SYSNDX DS CL13 char
|
||||
I&SYSNDX CVD ®,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
|
||||
|
|
|
|||
154
Task/N-queens-problem/AppleScript/n-queens-problem.applescript
Normal file
154
Task/N-queens-problem/AppleScript/n-queens-problem.applescript
Normal 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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
77
Task/N-queens-problem/Julia/n-queens-problem-1.julia
Normal file
77
Task/N-queens-problem/Julia/n-queens-problem-1.julia
Normal 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()
|
||||
68
Task/N-queens-problem/Julia/n-queens-problem-2.julia
Normal file
68
Task/N-queens-problem/Julia/n-queens-problem-2.julia
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
78
Task/N-queens-problem/PL-I/n-queens-problem.pli
Normal file
78
Task/N-queens-problem/PL-I/n-queens-problem.pli
Normal 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;
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
59
Task/N-queens-problem/PowerShell/n-queens-problem-1.psh
Normal file
59
Task/N-queens-problem/PowerShell/n-queens-problem-1.psh
Normal 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"
|
||||
}
|
||||
}
|
||||
7
Task/N-queens-problem/PowerShell/n-queens-problem-2.psh
Normal file
7
Task/N-queens-problem/PowerShell/n-queens-problem-2.psh
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Get-NQueensBoard 8
|
||||
''
|
||||
Get-NQueensBoard 3
|
||||
''
|
||||
Get-NQueensBoard 4
|
||||
''
|
||||
Get-NQueensBoard 14
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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?*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
77
Task/N-queens-problem/Rust/n-queens-problem-2.rust
Normal file
77
Task/N-queens-problem/Rust/n-queens-problem-2.rust
Normal 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
|
||||
}
|
||||
}
|
||||
|
|
@ -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, _))
|
||||
18
Task/N-queens-problem/Scala/n-queens-problem-2.scala
Normal file
18
Task/N-queens-problem/Scala/n-queens-problem-2.scala
Normal 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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue