|  | // $G $F.go && $L $F.$A  # don't run it - produces too much output | 
|  |  | 
|  | // Copyright 2010 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // This program solves the (English) peg solitaire board game. | 
|  | // See also: http://en.wikipedia.org/wiki/Peg_solitaire | 
|  |  | 
|  | package main | 
|  |  | 
|  | const N = 11 + 1 // length of a board row (+1 for newline) | 
|  |  | 
|  | // 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 = []int( | 
|  | `........... | 
|  | ........... | 
|  | ....●●●.... | 
|  | ....●●●.... | 
|  | ..●●●●●●●.. | 
|  | ..●●●○●●●.. | 
|  | ..●●●●●●●.. | 
|  | ....●●●.... | 
|  | ....●●●.... | 
|  | ........... | 
|  | ........... | 
|  | `) | 
|  |  | 
|  |  | 
|  | // 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) | 
|  | 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 | 
|  | println(string(board)) | 
|  | return true | 
|  | } | 
|  | // no solution found for this board | 
|  | return false | 
|  | } | 
|  |  | 
|  |  | 
|  | func main() { | 
|  | if !solve() { | 
|  | println("no solution found") | 
|  | } | 
|  | println(moves, "moves tried") | 
|  | } |