Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
108
Task/Knights-tour/Go/knights-tour-1.go
Normal file
108
Task/Knights-tour/Go/knights-tour-1.go
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
// input, 0-based start position
|
||||
const startRow = 0
|
||||
const startCol = 0
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
for !knightTour() {
|
||||
}
|
||||
}
|
||||
|
||||
var moves = []struct{ dr, dc int }{
|
||||
{2, 1},
|
||||
{2, -1},
|
||||
{1, 2},
|
||||
{1, -2},
|
||||
{-1, 2},
|
||||
{-1, -2},
|
||||
{-2, 1},
|
||||
{-2, -1},
|
||||
}
|
||||
|
||||
// Attempt knight tour starting at startRow, startCol using Warnsdorff's rule
|
||||
// and random tie breaking. If a tour is found, print it and return true.
|
||||
// Otherwise no backtracking, just return false.
|
||||
func knightTour() bool {
|
||||
// 8x8 board. squares hold 1-based visit order. 0 means unvisited.
|
||||
board := make([][]int, 8)
|
||||
for i := range board {
|
||||
board[i] = make([]int, 8)
|
||||
}
|
||||
r := startRow
|
||||
c := startCol
|
||||
board[r][c] = 1 // first move
|
||||
for move := 2; move <= 64; move++ {
|
||||
minNext := 8
|
||||
var mr, mc, nm int
|
||||
candidateMoves:
|
||||
for _, cm := range moves {
|
||||
cr := r + cm.dr
|
||||
if cr < 0 || cr >= 8 { // off board
|
||||
continue
|
||||
}
|
||||
cc := c + cm.dc
|
||||
if cc < 0 || cc >= 8 { // off board
|
||||
continue
|
||||
}
|
||||
if board[cr][cc] > 0 { // already visited
|
||||
continue
|
||||
}
|
||||
// cr, cc candidate legal move.
|
||||
p := 0 // count possible next moves.
|
||||
for _, m2 := range moves {
|
||||
r2 := cr + m2.dr
|
||||
if r2 < 0 || r2 >= 8 {
|
||||
continue
|
||||
}
|
||||
c2 := cc + m2.dc
|
||||
if c2 < 0 || c2 >= 8 {
|
||||
continue
|
||||
}
|
||||
if board[r2][c2] > 0 {
|
||||
continue
|
||||
}
|
||||
p++
|
||||
if p > minNext { // bail out as soon as it's eliminated
|
||||
continue candidateMoves
|
||||
}
|
||||
}
|
||||
if p < minNext { // it's better. keep it.
|
||||
minNext = p // new min possible next moves
|
||||
nm = 1 // number of candidates with this p
|
||||
mr = cr // best candidate move
|
||||
mc = cc
|
||||
continue
|
||||
}
|
||||
// it ties for best so far.
|
||||
// keep it with probability 1/(number of tying moves)
|
||||
nm++ // number of tying moves
|
||||
if rand.Intn(nm) == 0 { // one chance to keep it
|
||||
mr = cr
|
||||
mc = cc
|
||||
}
|
||||
}
|
||||
if nm == 0 { // no legal move
|
||||
return false
|
||||
}
|
||||
// make selected move
|
||||
r = mr
|
||||
c = mc
|
||||
board[r][c] = move
|
||||
}
|
||||
// tour complete. print board.
|
||||
for _, r := range board {
|
||||
for _, m := range r {
|
||||
fmt.Printf("%3d", m)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
return true
|
||||
}
|
||||
192
Task/Knights-tour/Go/knights-tour-2.go
Normal file
192
Task/Knights-tour/Go/knights-tour-2.go
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
/* Adapted from "Enumerating Knight's Tours using an Ant Colony Algorithm"
|
||||
by Philip Hingston and Graham Kendal,
|
||||
PDF at http://www.cs.nott.ac.uk/~gxk/papers/cec05knights.pdf. */
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const boardSize = 8
|
||||
const nSquares = boardSize * boardSize
|
||||
const completeTour = nSquares - 1
|
||||
|
||||
// task input: starting square. These are 1 based, but otherwise 0 based
|
||||
// row and column numbers are used througout the program.
|
||||
const rStart = 2
|
||||
const cStart = 3
|
||||
|
||||
// pheromone representation read by ants
|
||||
var tNet = make([]float64, nSquares*8)
|
||||
|
||||
// row, col deltas of legal moves
|
||||
var drc = [][]int{{1, 2}, {2, 1}, {2, -1}, {1, -2},
|
||||
{-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}}
|
||||
|
||||
// get square reached by following edge k from square (r, c)
|
||||
func dest(r, c, k int) (int, int, bool) {
|
||||
r += drc[k][0]
|
||||
c += drc[k][1]
|
||||
return r, c, r >= 0 && r < boardSize && c >= 0 && c < boardSize
|
||||
}
|
||||
|
||||
// struct represents a pheromone amount associated with a move
|
||||
type rckt struct {
|
||||
r, c, k int
|
||||
t float64
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("Starting square: row", rStart, "column", cStart)
|
||||
// initialize board
|
||||
for r := 0; r < boardSize; r++ {
|
||||
for c := 0; c < boardSize; c++ {
|
||||
for k := 0; k < 8; k++ {
|
||||
if _, _, ok := dest(r, c, k); ok {
|
||||
tNet[(r*boardSize+c)*8+k] = 1e-6
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// waitGroups for ant release clockwork
|
||||
var start, reset sync.WaitGroup
|
||||
start.Add(1)
|
||||
// channel for ants to return tours with pheremone updates
|
||||
tch := make(chan []rckt)
|
||||
|
||||
// create an ant for each square
|
||||
for r := 0; r < boardSize; r++ {
|
||||
for c := 0; c < boardSize; c++ {
|
||||
go ant(r, c, &start, &reset, tch)
|
||||
}
|
||||
}
|
||||
|
||||
// accumulator for new pheromone amounts
|
||||
tNew := make([]float64, nSquares*8)
|
||||
|
||||
// each iteration is a "cycle" as described in the paper
|
||||
for {
|
||||
// evaporate pheromones
|
||||
for i := range tNet {
|
||||
tNet[i] *= .75
|
||||
}
|
||||
|
||||
reset.Add(nSquares) // number of ants to release
|
||||
start.Done() // release them
|
||||
reset.Wait() // wait for them to begin searching
|
||||
start.Add(1) // reset start signal for next cycle
|
||||
|
||||
// gather tours from ants
|
||||
for i := 0; i < nSquares; i++ {
|
||||
tour := <-tch
|
||||
// watch for a complete tour from the specified starting square
|
||||
if len(tour) == completeTour &&
|
||||
tour[0].r == rStart-1 && tour[0].c == cStart-1 {
|
||||
|
||||
// task output: move sequence in a grid.
|
||||
seq := make([]int, nSquares)
|
||||
for i, sq := range tour {
|
||||
seq[sq.r*boardSize+sq.c] = i + 1
|
||||
}
|
||||
last := tour[len(tour)-1]
|
||||
r, c, _ := dest(last.r, last.c, last.k)
|
||||
seq[r*boardSize+c] = nSquares
|
||||
fmt.Println("Move sequence:")
|
||||
for r := 0; r < boardSize; r++ {
|
||||
for c := 0; c < boardSize; c++ {
|
||||
fmt.Printf(" %3d", seq[r*boardSize+c])
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
return // task only requires finding a single tour
|
||||
}
|
||||
// accumulate pheromone amounts from all ants
|
||||
for _, move := range tour {
|
||||
tNew[(move.r*boardSize+move.c)*8+move.k] += move.t
|
||||
}
|
||||
}
|
||||
|
||||
// update pheromone amounts on network, reset accumulator
|
||||
for i, tn := range tNew {
|
||||
tNet[i] += tn
|
||||
tNew[i] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type square struct {
|
||||
r, c int
|
||||
}
|
||||
|
||||
func ant(r, c int, start, reset *sync.WaitGroup, tourCh chan []rckt) {
|
||||
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
tabu := make([]square, nSquares)
|
||||
moves := make([]rckt, nSquares)
|
||||
unexp := make([]rckt, 8)
|
||||
tabu[0].r = r
|
||||
tabu[0].c = c
|
||||
|
||||
for {
|
||||
// cycle initialization
|
||||
moves = moves[:0]
|
||||
tabu = tabu[:1]
|
||||
r := tabu[0].r
|
||||
c := tabu[0].c
|
||||
|
||||
// wait for start signal
|
||||
start.Wait()
|
||||
reset.Done()
|
||||
|
||||
for {
|
||||
// choose next move
|
||||
unexp = unexp[:0]
|
||||
var tSum float64
|
||||
findU:
|
||||
for k := 0; k < 8; k++ {
|
||||
dr, dc, ok := dest(r, c, k)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, t := range tabu {
|
||||
if t.r == dr && t.c == dc {
|
||||
continue findU
|
||||
}
|
||||
}
|
||||
tk := tNet[(r*boardSize+c)*8+k]
|
||||
tSum += tk
|
||||
// note: dest r, c stored here
|
||||
unexp = append(unexp, rckt{dr, dc, k, tk})
|
||||
}
|
||||
if len(unexp) == 0 {
|
||||
break // no moves
|
||||
}
|
||||
rn := rnd.Float64() * tSum
|
||||
var move rckt
|
||||
for _, move = range unexp {
|
||||
if rn <= move.t {
|
||||
break
|
||||
}
|
||||
rn -= move.t
|
||||
}
|
||||
|
||||
// move to new square
|
||||
move.r, r = r, move.r
|
||||
move.c, c = c, move.c
|
||||
tabu = append(tabu, square{r, c})
|
||||
moves = append(moves, move)
|
||||
}
|
||||
|
||||
// compute pheromone amount to leave
|
||||
for i := range moves {
|
||||
moves[i].t = float64(len(moves)-i) / float64(completeTour-i)
|
||||
}
|
||||
|
||||
// return tour found for this cycle
|
||||
tourCh <- moves
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue