|  | // This program solves the (English) peg | 
|  | // solitaire board game. | 
|  | // http://en.wikipedia.org/wiki/Peg_solitaire | 
|  |  | 
|  | package main | 
|  |  | 
|  | import "fmt" | 
|  |  | 
|  | const N = 11 + 1 // length of a row (+1 for \n) | 
|  |  | 
|  | // The board must be surrounded by 2 illegal | 
|  | // fields in each direction so that move() | 
|  | // doesn't need to check the board boundaries. | 
|  | // Periods represent illegal fields, | 
|  | // ● are pegs, and ○ are holes. | 
|  |  | 
|  | var board = []rune( | 
|  | `........... | 
|  | ........... | 
|  | ....●●●.... | 
|  | ....●●●.... | 
|  | ..●●●●●●●.. | 
|  | ..●●●○●●●.. | 
|  | ..●●●●●●●.. | 
|  | ....●●●.... | 
|  | ....●●●.... | 
|  | ........... | 
|  | ........... | 
|  | `) | 
|  |  | 
|  | // center is the position of the center hole if | 
|  | // there is a single one; otherwise it is -1. | 
|  | var center int | 
|  |  | 
|  | func init() { | 
|  | n := 0 | 
|  | for pos, field := range board { | 
|  | if field == '○' { | 
|  | center = pos | 
|  | n++ | 
|  | } | 
|  | } | 
|  | if n != 1 { | 
|  | center = -1 // no single hole | 
|  | } | 
|  | } | 
|  |  | 
|  | var moves int // number of times move is called | 
|  |  | 
|  | // move tests if there is a peg at position pos that | 
|  | // can jump over another peg in direction dir. If the | 
|  | // move is valid, it is executed and move returns true. | 
|  | // Otherwise, move returns false. | 
|  | func move(pos, dir int) bool { | 
|  | moves++ | 
|  | if board[pos] == '●' && board[pos+dir] == '●' && board[pos+2*dir] == '○' { | 
|  | board[pos] = '○' | 
|  | board[pos+dir] = '○' | 
|  | board[pos+2*dir] = '●' | 
|  | return true | 
|  | } | 
|  | return false | 
|  | } | 
|  |  | 
|  | // unmove reverts a previously executed valid move. | 
|  | func unmove(pos, dir int) { | 
|  | board[pos] = '●' | 
|  | board[pos+dir] = '●' | 
|  | board[pos+2*dir] = '○' | 
|  | } | 
|  |  | 
|  | // solve tries to find a sequence of moves such that | 
|  | // there is only one peg left at the end; if center is | 
|  | // >= 0, that last peg must be in the center position. | 
|  | // If a solution is found, solve prints the board after | 
|  | // each move in a backward fashion (i.e., the last | 
|  | // board position is printed first, all the way back to | 
|  | // the starting board position). | 
|  | func solve() bool { | 
|  | var last, n int | 
|  | for pos, field := range board { | 
|  | // try each board position | 
|  | if field == '●' { | 
|  | // found a peg | 
|  | for _, dir := range [...]int{-1, -N, +1, +N} { | 
|  | // try each direction | 
|  | if move(pos, dir) { | 
|  | // a valid move was found and executed, | 
|  | // see if this new board has a solution | 
|  | if solve() { | 
|  | unmove(pos, dir) | 
|  | fmt.Println(string(board)) | 
|  | return true | 
|  | } | 
|  | unmove(pos, dir) | 
|  | } | 
|  | } | 
|  | last = pos | 
|  | n++ | 
|  | } | 
|  | } | 
|  | // tried each possible move | 
|  | if n == 1 && (center < 0 || last == center) { | 
|  | // there's only one peg left | 
|  | fmt.Println(string(board)) | 
|  | return true | 
|  | } | 
|  | // no solution found for this board | 
|  | return false | 
|  | } | 
|  |  | 
|  | func main() { | 
|  | if !solve() { | 
|  | fmt.Println("no solution found") | 
|  | } | 
|  | fmt.Println(moves, "moves tried") | 
|  | } |