func scanCage(s *domain.Sudoku) (bool, error) { rows := domain.BOARD_ROWS / 3 cols := domain.BOARD_COLS / 3 for i := 0; i < rows; i++ { for j := 0; j < cols; j++ { count := make([]int, 9) lastRow := make([]int, 9) lastCol := make([]int, 9) for row := i * 3; row < i*3+3; row++ { for col := j * 3; col < j*3+3; col++ { for n, mask := range AV_LIST { if s.Available[row*domain.BOARD_COLS+col]&mask == mask { count[n]++ lastRow[n] = row lastCol[n] = col } } } } // A hidden single in the cage has been found, solve it for j, c := range count { if c != 1 { continue } if s.Answer[lastRow[j]*domain.BOARD_COLS+lastCol[j]] != 0 { continue } fmt.Printf(" * Solving hidden single [cage]: %dx%d (%d)\n", lastCol[j], lastRow[j], j+1) if err := s.SolveCell(lastRow[j], lastCol[j], uint(j+1)); err != nil { return false, err } return true, nil } } } return false, nil }
func scanCol(s *domain.Sudoku) (bool, error) { for i := 0; i < domain.BOARD_COLS; i++ { count := make([]int, 9) lastRow := make([]int, 9) // Scan the rows for j := 0; j < domain.BOARD_ROWS; j++ { for n, mask := range AV_LIST { if s.Available[j*domain.BOARD_COLS+i]&mask == mask { count[n]++ lastRow[n] = j } } } // A hidden single in the col has been found, solve it for j, c := range count { if c != 1 { continue } if s.Answer[lastRow[j]*domain.BOARD_COLS+i] != 0 { continue } fmt.Printf(" * Solving hidden single [col]: %dx%d (%d)\n", i, lastRow[j], j+1) if err := s.SolveCell(lastRow[j], i, uint(j+1)); err != nil { return false, err } return true, nil } } return false, nil }
func solve(s *domain.Sudoku) error { // Always print the final sudoku before exiting defer s.Print() // Apply the cages combinations read from the data file if err := strategies.KillerCombinations(s); err != nil { return err } // List of strategies we can apply, ordered from simpler and quicker to // more complex and slower slist := []Strategy{ strategies.HiddenSingles, strategies.NakedPairs, } for { // Check if the puzzle is solved if s.Solved() { return nil } // Check for solved squares if done, err := s.SolvedSquares(); err != nil { return err } else if done { continue } // Apply all the strategies to the sudoku // until one modifies the content i := 0 for _, strat := range slist { i += 1 if done, err := strat(s); err != nil { return err } else if done { i -= 1 break } } // The puzzle can't be solved if i == len(slist) { break } } fmt.Println("ERROR: No more strategies to try. Puzzle unsolvable") return nil //return domain.NewErrorf("no more strategies to try. puzzle unsolvable") }