minimize the number of guesses to reduce non-polynomial time component

This commit is contained in:
overflowerror 2021-01-04 21:38:15 +01:00
parent 3b59dfc374
commit 4362be5345

76
main.go
View file

@ -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)
} }