mirror of
https://github.com/sigmasternchen/sudoku-solver
synced 2025-03-15 07:48:56 +00:00
minimize the number of guesses to reduce non-polynomial time component
This commit is contained in:
parent
3b59dfc374
commit
4362be5345
1 changed files with 44 additions and 32 deletions
76
main.go
76
main.go
|
@ -19,8 +19,8 @@ const blockSize = size / blocks
|
||||||
|
|
||||||
const maskZero = (1 << size) - 1
|
const maskZero = (1 << size) - 1
|
||||||
|
|
||||||
const guessChanSize = 1<<20
|
const guessChanSize = 1 << 20
|
||||||
const eliminatedChanSize = 1<<15
|
const eliminatedChanSize = 1 << 15
|
||||||
|
|
||||||
type field [size][size][]int
|
type field [size][size][]int
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ func eliminate(field *field) *int {
|
||||||
if len(field[x][y]) == 1 {
|
if len(field[x][y]) == 1 {
|
||||||
mask := 1 << (field[x][y][0] - 1)
|
mask := 1 << (field[x][y][0] - 1)
|
||||||
|
|
||||||
if bitfield & mask == 0 {
|
if bitfield&mask == 0 {
|
||||||
// duplicate number
|
// duplicate number
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,8 @@ func eliminate(field *field) *int {
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
if (bitfield & (1 << (field[x][y][i] - 1))) == 0 {
|
if (bitfield & (1 << (field[x][y][i] - 1))) == 0 {
|
||||||
eliminated++
|
eliminated++
|
||||||
field[x][y][i] = field[x][y][length - 1]
|
field[x][y][i] = field[x][y][length-1]
|
||||||
field[x][y] = field[x][y][:length - 1]
|
field[x][y] = field[x][y][:length-1]
|
||||||
length--
|
length--
|
||||||
i--
|
i--
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ func eliminate(field *field) *int {
|
||||||
if len(field[x][y]) == 1 {
|
if len(field[x][y]) == 1 {
|
||||||
mask := 1 << (field[x][y][0] - 1)
|
mask := 1 << (field[x][y][0] - 1)
|
||||||
|
|
||||||
if bitfield & mask == 0 {
|
if bitfield&mask == 0 {
|
||||||
// duplicate number
|
// duplicate number
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -96,8 +96,8 @@ func eliminate(field *field) *int {
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
if (bitfield & (1 << (field[x][y][i] - 1))) == 0 {
|
if (bitfield & (1 << (field[x][y][i] - 1))) == 0 {
|
||||||
eliminated++
|
eliminated++
|
||||||
field[x][y][i] = field[x][y][length - 1]
|
field[x][y][i] = field[x][y][length-1]
|
||||||
field[x][y] = field[x][y][:length - 1]
|
field[x][y] = field[x][y][:length-1]
|
||||||
length--
|
length--
|
||||||
i--
|
i--
|
||||||
}
|
}
|
||||||
|
@ -115,12 +115,12 @@ func eliminate(field *field) *int {
|
||||||
for sy := 0; sy < blocks; sy++ {
|
for sy := 0; sy < blocks; sy++ {
|
||||||
bitfield := maskZero
|
bitfield := maskZero
|
||||||
|
|
||||||
for x := sx * blockSize; x < (sx + 1) * blockSize; x++ {
|
for x := sx * blockSize; x < (sx+1)*blockSize; x++ {
|
||||||
for y := sy * blockSize; y < (sy + 1) * blockSize; y++ {
|
for y := sy * blockSize; y < (sy+1)*blockSize; y++ {
|
||||||
if len(field[x][y]) == 1 {
|
if len(field[x][y]) == 1 {
|
||||||
mask := 1 << (field[x][y][0] - 1)
|
mask := 1 << (field[x][y][0] - 1)
|
||||||
|
|
||||||
if bitfield & mask == 0 {
|
if bitfield&mask == 0 {
|
||||||
// duplicate number
|
// duplicate number
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -130,8 +130,8 @@ func eliminate(field *field) *int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for x := sx * blockSize; x < (sx + 1) * blockSize; x++ {
|
for x := sx * blockSize; x < (sx+1)*blockSize; x++ {
|
||||||
for y := sy * blockSize; y < (sy + 1) * blockSize; y++ {
|
for y := sy * blockSize; y < (sy+1)*blockSize; y++ {
|
||||||
if len(field[x][y]) != 1 {
|
if len(field[x][y]) != 1 {
|
||||||
length := len(field[x][y])
|
length := len(field[x][y])
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
|
@ -157,6 +157,7 @@ func eliminate(field *field) *int {
|
||||||
}
|
}
|
||||||
|
|
||||||
type result int
|
type result int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
unsolved result = iota
|
unsolved result = iota
|
||||||
solved
|
solved
|
||||||
|
@ -192,21 +193,32 @@ func copyField(fieldToCopy field) field {
|
||||||
}
|
}
|
||||||
|
|
||||||
func addGuesses(field field) {
|
func addGuesses(field field) {
|
||||||
|
hasGuess := false
|
||||||
|
minX := 0
|
||||||
|
minY := 0
|
||||||
|
minLength := size + 1
|
||||||
|
|
||||||
for x := 0; x < size; x++ {
|
for x := 0; x < size; x++ {
|
||||||
for y := 0; y < size; y++ {
|
for y := 0; y < size; y++ {
|
||||||
if len(field[x][y]) > 1 {
|
length := len(field[x][y])
|
||||||
for _, value := range field[x][y] {
|
if length > 1 && length < minLength {
|
||||||
newField := copyField(field)
|
hasGuess = true
|
||||||
newField[x][y] = []int{value}
|
minX = x
|
||||||
|
minY = y
|
||||||
atomic.AddInt64(&possibilities, 1)
|
minLength = length
|
||||||
guesses <- newField
|
|
||||||
}
|
|
||||||
// we don't need to add more
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hasGuess {
|
||||||
|
for _, value := range field[minX][minY] {
|
||||||
|
newField := copyField(field)
|
||||||
|
newField[minX][minY] = []int{value}
|
||||||
|
|
||||||
|
atomic.AddInt64(&possibilities, 1)
|
||||||
|
guesses <- newField
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removePossibility() {
|
func removePossibility() {
|
||||||
|
@ -217,11 +229,11 @@ func removePossibility() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func worker() {
|
func worker() {
|
||||||
workerLoop:
|
workerLoop:
|
||||||
|
|
||||||
for {
|
for {
|
||||||
field := <- guesses
|
field := <-guesses
|
||||||
eliminateLoop:
|
eliminateLoop:
|
||||||
for {
|
for {
|
||||||
eliminated := eliminate(&field)
|
eliminated := eliminate(&field)
|
||||||
if eliminated == nil {
|
if eliminated == nil {
|
||||||
|
@ -253,7 +265,7 @@ func worker() {
|
||||||
func all() []int {
|
func all() []int {
|
||||||
var list []int
|
var list []int
|
||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
list = append(list, i + 1)
|
list = append(list, i+1)
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
@ -315,9 +327,9 @@ func printField(field field) {
|
||||||
} else if len(field[x][y]) == 1 {
|
} else if len(field[x][y]) == 1 {
|
||||||
value := field[x][y][0]
|
value := field[x][y][0]
|
||||||
if value < 10 {
|
if value < 10 {
|
||||||
fmt.Printf("%c", rune(value + '0'))
|
fmt.Printf("%c", rune(value+'0'))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("%c", rune(value - 10 + 'a'))
|
fmt.Printf("%c", rune(value-10+'a'))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Print(" ")
|
fmt.Print(" ")
|
||||||
|
@ -329,7 +341,7 @@ func printField(field field) {
|
||||||
|
|
||||||
func eliminiatedCounter() {
|
func eliminiatedCounter() {
|
||||||
for {
|
for {
|
||||||
eliminiated := <- eliminatedChan
|
eliminiated := <-eliminatedChan
|
||||||
globalEliminated += int64(eliminiated)
|
globalEliminated += int64(eliminiated)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,7 +449,7 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
solution := <- solution
|
solution := <-solution
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
@ -445,4 +457,4 @@ func main() {
|
||||||
fmt.Println("solved")
|
fmt.Println("solved")
|
||||||
|
|
||||||
printField(solution)
|
printField(solution)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue