go語言-數獨求解

package main

import (
	"container/list"
	"fmt"
)

var (
	ROWCOUNT = 9
)

//每一步的數據
type stepData struct {
	x    int
	y    int
	data []int

	backup int
}

//獲得數組的行列數據
func getRowColData(info [][]int, row, col int) []int {
	returnArr := make([]int, 0, ROWCOUNT)
	hasInfo := make(map[int]bool)
	for i := 0; i < len(info[row]); i++ {
		curDta := info[row][i]
		if _, ok := hasInfo[curDta]; !ok {
			returnArr = append(returnArr, curDta)
			hasInfo[curDta] = true
		}
	}

	for i := 0; i < len(info); i++ {
		curDta := info[i][col]
		if _, ok := hasInfo[curDta]; !ok {
			returnArr = append(returnArr, curDta)
			hasInfo[curDta] = true
		}
	}

	return returnArr
}

//獲得前一個數組不在後一個數組中的元素
func getDiffInfo(refer []int, cur []int) []int {
	hasInfo := make(map[int]bool)
	for i := 0; i < len(refer); i++ {
		hasInfo[refer[i]] = true
	}

	returnArr := make([]int, 0, len(cur))
	for i := 0; i < len(cur); i++ {
		if _, ok := hasInfo[cur[i]]; !ok {
			returnArr = append(returnArr, cur[i])
		}
	}

	return returnArr
}

//判斷元素是否符合數獨的規則
func isvalid(info [][]int, row, col, value int) bool {
	for i := 0; i < len(info[row]); i++ {
		if i == col {
			continue
		}
		curDta := info[row][i]
		if curDta == value {
			return false
		}
	}

	for i := 0; i < len(info); i++ {
		if i == row {
			continue
		}
		curDta := info[i][col]
		if curDta == value {
			return false
		}
	}

	return true
}

//獲得x、y位置的step數據
func getStepData(dstValue [][]int, x, y int) *stepData {
	curStep := &stepData{
		x:      x,
		y:      y,
		data:   make([]int, 0, ROWCOUNT),
		backup: 0,
	}

	if dstValue[x][y] != 0 {
		curStep.data = append(curStep.data, dstValue[x][y])
		curStep.backup = dstValue[x][y]
	} else {
		for k := 0; k < 9; k++ {
			curStep.data = append(curStep.data, k+1)
		}

		curStep.data = getDiffInfo(getRowColData(dstValue, x, y), curStep.data)
	}

	return curStep
}

//創建要求解的數獨
func buildSudoku() [][]int {
	dstValue := make([][]int, ROWCOUNT, ROWCOUNT)
	for i := 0; i < 9; i++ {
		dstValue[i] = make([]int, ROWCOUNT, ROWCOUNT)
	}

	dstValue[0][5] = 5
	dstValue[0][8] = 7

	dstValue[1][1] = 6
	dstValue[1][2] = 5
	dstValue[1][3] = 3
	dstValue[1][4] = 9
	dstValue[1][6] = 1

	dstValue[2][1] = 8
	dstValue[2][4] = 6
	dstValue[2][7] = 5

	dstValue[3][0] = 6
	dstValue[3][1] = 3
	dstValue[3][2] = 2
	dstValue[3][5] = 9
	dstValue[3][7] = 7

	dstValue[4][1] = 7
	dstValue[4][3] = 4
	dstValue[4][5] = 1
	dstValue[4][7] = 6

	dstValue[5][1] = 1
	dstValue[5][3] = 2
	dstValue[5][6] = 3
	dstValue[5][7] = 9
	dstValue[5][8] = 5

	dstValue[6][1] = 9
	dstValue[6][4] = 2
	dstValue[6][7] = 8

	dstValue[7][2] = 8
	dstValue[7][4] = 1
	dstValue[7][5] = 3
	dstValue[7][6] = 7
	dstValue[7][7] = 4

	dstValue[8][0] = 7
	dstValue[8][3] = 6

	return dstValue
}

func main() {
	dstValue := buildSudoku()

	myList := list.New()
	myList.PushFront(getStepData(dstValue, 0, 0))

	var count int
	for {
		curStepData := myList.Front().Value.(*stepData)

		if len(curStepData.data) < 1 {
			dstValue[curStepData.x][curStepData.y] = curStepData.backup
			myList.Remove(myList.Front())
			if myList.Len() < 1 {
				fmt.Println("list is null, ", curStepData.x, " : ", curStepData.y)
				break
			}

			continue
		}

		for {
			if len(curStepData.data) < 1 {
				dstValue[curStepData.x][curStepData.y] = curStepData.backup
				break
			}

			preStepData := curStepData.data[0]
			curStepData.data = curStepData.data[1:]
			if isvalid(dstValue, curStepData.x, curStepData.y, preStepData) {
				dstValue[curStepData.x][curStepData.y] = preStepData

				xPos := curStepData.x
				yPos := curStepData.y

				if curStepData.x == (ROWCOUNT-1) && curStepData.y == (ROWCOUNT-1) {
					fmt.Println("success")
					fmt.Println(dstValue)
					count++
					break
				}

				yPos += 1
				if yPos >= ROWCOUNT {
					yPos -= ROWCOUNT
					xPos += 1
				}

				myList.PushFront(getStepData(dstValue, xPos, yPos))

				break
			}
		}
	}

	fmt.Println("cout: ", count)
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章