package solver import ( "flag" "fmt" "log" "os" "runtime" ) func (solver *Solver) parseFlags() { // Define variables var row1 string var row2 string var row3 string var row4 string var row5 string var row6 string var row7 string var row8 string var row9 string var split int var part int // Define parameters flag.StringVar(&row1, "row1", "000000000", "1st row of the sudoku puzzle.") flag.StringVar(&row2, "row2", "000000000", "2nd row of the sudoku puzzle.") flag.StringVar(&row3, "row3", "000000000", "4rd row of the sudoku puzzle.") flag.StringVar(&row4, "row4", "000000000", "4th row of the sudoku puzzle.") flag.StringVar(&row5, "row5", "000000000", "5th row of the sudoku puzzle.") flag.StringVar(&row6, "row6", "000000000", "6th row of the sudoku puzzle.") flag.StringVar(&row7, "row7", "000000000", "7th row of the sudoku puzzle.") flag.StringVar(&row8, "row8", "000000000", "8th row of the sudoku puzzle.") flag.StringVar(&row9, "row9", "000000000", "9th row of the sudoku puzzle.") flag.IntVar(&solver.numCPUs, "numcpu", runtime.NumCPU(), "Number of CPU cores to assign to this task.") flag.IntVar(&split, "split", 1, "Split the tasks in n parts. This depends on the availability of the first row.") flag.IntVar(&part, "part", 1, "Process part x in n parts. Cannot be lower than 1, or higher than specified in split.") // Parse the flags flag.Parse() // Process any changes to the CPU usage. if solver.numCPUs <= 0 { log.Printf("ERROR: Number of CPU cores must be 1 or higher.\n\n") solver.printUsage() os.Exit(1) } if solver.numCPUs != runtime.NumCPU() { runtime.GOMAXPROCS(solver.numCPUs) } // Process rows if row1 == "000000000" || row2 == "000000000" || row3 == "000000000" || row4 == "000000000" || row5 == "000000000" || row6 == "000000000" || row7 == "000000000" || row8 == "000000000" || row9 == "000000000" { log.Printf("ERROR: All parameters must be entered.\n\n") solver.printUsage() os.Exit(1) } // Validate the row (never trust user input) solver.validateRow("row1", row1) solver.validateRow("row2", row2) solver.validateRow("row3", row3) solver.validateRow("row4", row4) solver.validateRow("row5", row5) solver.validateRow("row6", row6) solver.validateRow("row7", row7) solver.validateRow("row8", row8) solver.validateRow("row9", row9) // Put entries in into the struct solver.row1 = row1 solver.row2 = row2 solver.row3 = row3 solver.row4 = row4 solver.row5 = row5 solver.row6 = row6 solver.row7 = row7 solver.row8 = row8 solver.row9 = row9 // Process workload splitting // Ensure split and part are 1 or higher if split <= 0 || part <= 0 { log.Printf("ERROR: '-split' and '-part' need to be 1 or higher.\n") solver.printUsage() os.Exit(1) } // Ensure part is between 1 and split if part > split { log.Printf("ERROR: '-part' cannot be bigger than `-split`.\n") solver.printUsage() os.Exit(1) } solver.split = split solver.part = part } func (solver *Solver) validateRow(name string, row string) { var found bool var double bool count := make(map[rune]int) // 1. Make sure the row is 9 in length if len(row) != 9 { log.Printf("ERROR: Invalid length of %s (%s), must be 9 numbers\n\n", name, row) solver.printUsage() os.Exit(1) } // 2. Ensure all digits are numbers for _, value := range row { found = solver.validChar(value) } if !found { log.Printf("ERROR: Invalid character of %s (%s), must be 9 numbers\n\n", name, row) solver.printUsage() os.Exit(1) } // 3. Ensure all digits (except zero) are there only once for _, digits := range row { count[digits] = count[digits] + 1 } for key, value := range count { if value > 1 && key != 48 { double = true } } if double { log.Printf("ERROR: Double character of %s (%s), numbers between 1 and 9 may only be entered once\n\n", name, row) solver.printUsage() os.Exit(1) } } func (solver *Solver) validChar(char rune) (valid bool) { decvals := [10]int{48, 49, 50, 51, 52, 53, 54, 55, 56, 57} for _, value := range decvals { if char == rune(value) { valid = true } } return valid } func (solver *Solver) printUsage() { fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0]) fmt.Fprintf(flag.CommandLine.Output(), "\nPut every row of a Sudoku puzzle as paramters.\nUse '0' for what is currently blank in the puzzle you wish to solve.\n\n") fmt.Fprintf(flag.CommandLine.Output(), "Example: %s -row1 ... -row2 ... -row3 ... (etc)\n\n", os.Args[0]) flag.PrintDefaults() }