Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
61
Task/N-queens-problem/Go/n-queens-problem-1.go
Normal file
61
Task/N-queens-problem/Go/n-queens-problem-1.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// A fairly literal translation of the example program on the referenced
|
||||
// WP page. Well, it happened to be the example program the day I completed
|
||||
// the task. It seems from the WP history that there has been some churn
|
||||
// in the posted example program. The example program of the day was in
|
||||
// Pascal and was credited to Niklaus Wirth, from his "Algorithms +
|
||||
// Data Structures = Programs."
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var (
|
||||
i int
|
||||
q bool
|
||||
a [9]bool
|
||||
b [17]bool
|
||||
c [15]bool // offset by 7 relative to the Pascal version
|
||||
x [9]int
|
||||
)
|
||||
|
||||
func try(i int) {
|
||||
for j := 1; ; j++ {
|
||||
q = false
|
||||
if a[j] && b[i+j] && c[i-j+7] {
|
||||
x[i] = j
|
||||
a[j] = false
|
||||
b[i+j] = false
|
||||
c[i-j+7] = false
|
||||
if i < 8 {
|
||||
try(i + 1)
|
||||
if !q {
|
||||
a[j] = true
|
||||
b[i+j] = true
|
||||
c[i-j+7] = true
|
||||
}
|
||||
} else {
|
||||
q = true
|
||||
}
|
||||
}
|
||||
if q || j == 8 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
for i := 1; i <= 8; i++ {
|
||||
a[i] = true
|
||||
}
|
||||
for i := 2; i <= 16; i++ {
|
||||
b[i] = true
|
||||
}
|
||||
for i := 0; i <= 14; i++ {
|
||||
c[i] = true
|
||||
}
|
||||
try(1)
|
||||
if q {
|
||||
for i := 1; i <= 8; i++ {
|
||||
fmt.Println(i, x[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
124
Task/N-queens-problem/Go/n-queens-problem-2.go
Normal file
124
Task/N-queens-problem/Go/n-queens-problem-2.go
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* N-Queens Problem
|
||||
*
|
||||
* For an NxN chess board, 'safely' place a chess queen in every column and row such that none can attack another.
|
||||
* This solution is based Wirth Pascal solution, although a tad cleaner, thus easier to understand as it uses Go/C
|
||||
* style indexing and naming, and also prints the Queen using a Unicode 'rune' (which other languages do not handle natively).
|
||||
*
|
||||
* N rows by N columns are number left to right top to bottom 0 - 7
|
||||
*
|
||||
* There are 2N-1 diagonals (showing an 8x8)
|
||||
* the upper-right to lower-left are numbered row + col that is:
|
||||
* 0 1 2 3 4 5 6 7
|
||||
* 1 2 3 4 5 6 7 8
|
||||
* 2 3 4 5 6 7 8 9
|
||||
* 3 4 5 6 7 8 9 10
|
||||
* 4 5 6 7 8 9 10 11
|
||||
* 5 6 7 8 9 10 11 12
|
||||
* 6 7 8 9 10 11 12 13
|
||||
* 7 8 9 10 11 12 13 14
|
||||
*
|
||||
* the upper-left to lower-right are numbered N-1 + row - col
|
||||
* 7 6 5 4 3 2 1 0
|
||||
* 8 7 6 5 4 3 2 1
|
||||
* 9 8 7 6 5 4 3 2
|
||||
* 10 9 8 7 6 5 4 3
|
||||
* 11 10 9 8 7 6 5 4
|
||||
* 12 11 10 9 8 7 6 5
|
||||
* 13 12 11 10 9 8 7 6
|
||||
* 14 13 12 11 10 9 8 7
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
const N = 8
|
||||
const HAS_QUEEN = false
|
||||
const EMPTY = true
|
||||
const UNASSIGNED = -1
|
||||
const white_queen = '\u2655'
|
||||
|
||||
|
||||
var row_num[N]int // results, indexed by row will be the column where the queen lives (UNASSIGNED) is empty
|
||||
var right_2_left_diag[(2*N-1)]bool // T if no queen in diag[idx]: row i, column col is diag i+col
|
||||
var left_2_right_diag[(2*N-1)]bool // T is no queen in diag[idx], row i, column col is N-1 + i-col
|
||||
|
||||
|
||||
func printresults() {
|
||||
for col := 0; col < N; col++ {
|
||||
if col != 0 {
|
||||
fmt.Printf(" ");
|
||||
}
|
||||
fmt.Printf("%d,%d", col, row_num[col])
|
||||
}
|
||||
fmt.Printf("\n");
|
||||
for row := 0; row < N; row++ {
|
||||
for col := 0; col < N; col++ {
|
||||
if col == row_num[row] {
|
||||
fmt.Printf(" %c ", white_queen)
|
||||
} else {
|
||||
fmt.Printf(" . ")
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* save a queen on the board by saving where we think it should go, and marking the diagonals as occupied
|
||||
*/
|
||||
|
||||
func savequeen(row int, col int) {
|
||||
row_num[row] = col // save queen column for this row
|
||||
right_2_left_diag[row+col] = HAS_QUEEN // mark forward diags as occupied
|
||||
left_2_right_diag[row-col+(N-1)] = HAS_QUEEN // mark backward diags as occupied
|
||||
}
|
||||
|
||||
/*
|
||||
* backout a previously saved queen by clearing where we put it, and marking the diagonals as empty
|
||||
*/
|
||||
|
||||
func clearqueen(row int, col int) {
|
||||
row_num[row] = UNASSIGNED
|
||||
right_2_left_diag[row+col] = EMPTY
|
||||
left_2_right_diag[row-col+(N-1)] = EMPTY
|
||||
}
|
||||
|
||||
/*
|
||||
* for each column try the solutions
|
||||
*/
|
||||
func trycol(col int) bool {
|
||||
// check each row to look for the first empty row that does not have a diagonal in use too
|
||||
for row := 0; row < N; row++ {
|
||||
if row_num[row] == UNASSIGNED && // has the row been used yet?
|
||||
right_2_left_diag[row+col] == EMPTY && // check for the forward diags
|
||||
left_2_right_diag[row-col+(N-1)] == EMPTY { // check for the backwards diags
|
||||
savequeen(row, col) // this is a possible solution
|
||||
// Tricky part here: going forward thru the col up to but not including the rightmost one
|
||||
// if this fails, we are done, no need to search any more
|
||||
if col < N-1 && !trycol(col+1) {
|
||||
// ok this did not work - we need to try a different row, so undo the guess
|
||||
clearqueen(row, col)
|
||||
} else {
|
||||
// we have a solution on this row/col, start popping the stack.
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false // not a solution for this col, pop the stack, undo the last guess, and try the next one
|
||||
}
|
||||
|
||||
func main() {
|
||||
for i := 0; i < N ; i++ {
|
||||
row_num[i] = UNASSIGNED
|
||||
}
|
||||
for i := 0; i < 2*N-1 ; i++ {
|
||||
right_2_left_diag[i] = EMPTY
|
||||
}
|
||||
for i := 0; i < 2*N-1 ; i++ {
|
||||
left_2_right_diag[i] = EMPTY
|
||||
}
|
||||
trycol(0)
|
||||
printresults()
|
||||
}
|
||||
136
Task/N-queens-problem/Go/n-queens-problem-3.go
Normal file
136
Task/N-queens-problem/Go/n-queens-problem-3.go
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"rosettacode.org/dlx" // or where ever you put the dlx package
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetPrefix("N-queens: ")
|
||||
log.SetFlags(0)
|
||||
profile := flag.Bool("profile", false, "show DLX profile")
|
||||
flag.Parse()
|
||||
|
||||
for N := 2; N <= 18; N++ {
|
||||
err := nqueens(N, N == 8, *profile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func nqueens(N int, printFirst, profile bool) error {
|
||||
// Build a new DLX matrix with 2N primary columns and 4N-6 secondary
|
||||
// columns: R0..R(N-1), F0..F(N-1), A1..A(2N-3), B1..B(2N-3).
|
||||
// We also know the number of cells and solution rows required.
|
||||
m := dlx.NewWithHint(2*N, 4*N-6, N*N*4-4, 8)
|
||||
|
||||
s := solution{
|
||||
N: N,
|
||||
renumFwd: make([]int, 0, 2*N),
|
||||
renumBack: make([]int, 2*N),
|
||||
printFirst: printFirst,
|
||||
}
|
||||
|
||||
// column indexes
|
||||
iR0 := 0
|
||||
iF0 := iR0 + N
|
||||
iA1 := iF0 + N
|
||||
iB1 := iA1 + 2*N - 3
|
||||
|
||||
// Use "organ-pipe" ordering. E.g. for N=8:
|
||||
// R4 F4 R3 F3 R5 F5 R2 F2 R6 F6 R1 F1 R7 F7 R0 F0
|
||||
// This can reduce the number of link updates required by
|
||||
// almost half for large N; see Knuth's paper for details.
|
||||
mid := N / 2
|
||||
for off := 0; off <= N-mid; off++ {
|
||||
i := mid - off
|
||||
if i >= 0 {
|
||||
s.renumBack[iR0+i] = len(s.renumFwd)
|
||||
s.renumBack[iF0+i] = len(s.renumFwd) + 1
|
||||
s.renumFwd = append(s.renumFwd, iR0+i, iF0+i)
|
||||
}
|
||||
if i = mid + off; off != 0 && i < N {
|
||||
s.renumBack[iR0+i] = len(s.renumFwd)
|
||||
s.renumBack[iF0+i] = len(s.renumFwd) + 1
|
||||
s.renumFwd = append(s.renumFwd, iR0+i, iF0+i)
|
||||
}
|
||||
}
|
||||
|
||||
// Add constraint rows.
|
||||
// TODO: pre-eliminate symetrical possibilities.
|
||||
cols := make([]int, 4)
|
||||
for i := 0; i < N; i++ {
|
||||
for j := 0; j < N; j++ {
|
||||
cols[0] = iR0 + i // Ri, rank i
|
||||
cols[1] = iF0 + j // Fj, file j
|
||||
a := (i + j) // A(i+j), diagonals
|
||||
b := (N - 1 - i + j) // B(N-1-i+j), reverse diagonals
|
||||
cols = cols[:2]
|
||||
// Do organ-pipe reordering for R and F.
|
||||
for i, c := range cols {
|
||||
cols[i] = s.renumBack[c]
|
||||
}
|
||||
|
||||
// Only add diagonals with more than one space; that
|
||||
// is we omit the corners: A0, A(2N-2), B0, and B(2N-2)
|
||||
if 0 < a && a < 2*N-2 {
|
||||
cols = append(cols, iA1+a-1)
|
||||
}
|
||||
if 0 < b && b < 2*N-2 {
|
||||
cols = append(cols, iB1+b-1)
|
||||
}
|
||||
|
||||
m.AddRow(cols)
|
||||
}
|
||||
}
|
||||
|
||||
// Search for solutions.
|
||||
start := time.Now()
|
||||
err := m.Search(s.found)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("%d×%d queens has %2d solutions, found in %v\n", N, N, s.count, elapsed)
|
||||
if profile {
|
||||
m.ProfileWrite(os.Stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type solution struct {
|
||||
N int
|
||||
count int
|
||||
renumFwd []int // for "organ-pipe" column ordering
|
||||
renumBack []int
|
||||
printFirst bool
|
||||
}
|
||||
|
||||
func (s *solution) found(m *dlx.Matrix) error {
|
||||
s.count++
|
||||
if s.printFirst && s.count == 1 {
|
||||
fmt.Printf("First %d×%d queens solution:\n", s.N, s.N)
|
||||
for _, cols := range m.SolutionIDs(nil) {
|
||||
var r, f int
|
||||
for _, c := range cols {
|
||||
// Undo organ-pipe reodering
|
||||
if c < len(s.renumFwd) {
|
||||
c = s.renumFwd[c]
|
||||
}
|
||||
if c < s.N {
|
||||
r = c + 1
|
||||
} else if c < 2*s.N {
|
||||
f = c - s.N + 1
|
||||
}
|
||||
}
|
||||
fmt.Printf(" R%d F%d\n", r, f)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue