2025-01-23 22:39:59 +01:00
package solver
import (
"flag"
"fmt"
"log"
"os"
2025-01-25 19:45:31 +01:00
"runtime"
2025-01-23 22:39:59 +01:00
)
2025-01-27 19:40:24 +01:00
func ( solver * Solver ) parseFlags ( ) {
2025-01-23 22:39:59 +01:00
// 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
2025-01-27 00:13:00 +01:00
var split int
var part int
2025-01-23 22:39:59 +01:00
// 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." )
2025-01-27 19:40:24 +01:00
flag . IntVar ( & solver . numCPUs , "numcpu" , runtime . NumCPU ( ) , "Number of CPU cores to assign to this task." )
2025-01-27 00:13:00 +01:00
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." )
2025-01-23 22:39:59 +01:00
// Parse the flags
flag . Parse ( )
2025-01-27 00:13:00 +01:00
// Process any changes to the CPU usage.
2025-01-27 19:40:24 +01:00
if solver . numCPUs <= 0 {
2025-01-25 19:45:31 +01:00
log . Printf ( "ERROR: Number of CPU cores must be 1 or higher.\n\n" )
2025-01-27 19:40:24 +01:00
solver . printUsage ( )
2025-01-25 19:45:31 +01:00
os . Exit ( 1 )
}
2025-01-27 19:40:24 +01:00
if solver . numCPUs != runtime . NumCPU ( ) {
runtime . GOMAXPROCS ( solver . numCPUs )
2025-01-25 19:45:31 +01:00
}
2025-01-27 00:13:00 +01:00
// Process rows
2025-01-23 23:55:40 +01:00
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" )
2025-01-27 19:40:24 +01:00
solver . printUsage ( )
2025-01-23 23:55:40 +01:00
os . Exit ( 1 )
}
2025-01-23 22:39:59 +01:00
// Validate the row (never trust user input)
2025-01-27 19:40:24 +01:00
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 )
2025-01-23 22:39:59 +01:00
// 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
2025-01-27 00:13:00 +01:00
// 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" )
2025-01-27 19:40:24 +01:00
solver . printUsage ( )
2025-01-27 00:13:00 +01:00
os . Exit ( 1 )
}
// Ensure part is between 1 and split
if part > split {
log . Printf ( "ERROR: '-part' cannot be bigger than `-split`.\n" )
2025-01-27 19:40:24 +01:00
solver . printUsage ( )
2025-01-27 00:13:00 +01:00
os . Exit ( 1 )
}
solver . split = split
solver . part = part
2025-01-23 22:39:59 +01:00
}
2025-01-27 19:40:24 +01:00
func ( solver * Solver ) validateRow ( name string , row string ) {
2025-01-23 22:39:59 +01:00
var found bool
var double bool
count := make ( map [ rune ] int )
// 1. Make sure the row is 9 in length
if len ( row ) != 9 {
2025-01-23 23:55:40 +01:00
log . Printf ( "ERROR: Invalid length of %s (%s), must be 9 numbers\n\n" , name , row )
2025-01-27 19:40:24 +01:00
solver . printUsage ( )
2025-01-23 22:39:59 +01:00
os . Exit ( 1 )
}
// 2. Ensure all digits are numbers
for _ , value := range row {
2025-01-27 19:40:24 +01:00
found = solver . validChar ( value )
2025-01-23 22:39:59 +01:00
}
if ! found {
2025-01-23 23:55:40 +01:00
log . Printf ( "ERROR: Invalid character of %s (%s), must be 9 numbers\n\n" , name , row )
2025-01-27 19:40:24 +01:00
solver . printUsage ( )
2025-01-23 22:39:59 +01:00
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 {
2025-01-23 23:55:40 +01:00
log . Printf ( "ERROR: Double character of %s (%s), numbers between 1 and 9 may only be entered once\n\n" , name , row )
2025-01-27 19:40:24 +01:00
solver . printUsage ( )
2025-01-23 22:39:59 +01:00
os . Exit ( 1 )
}
}
2025-01-27 19:40:24 +01:00
func ( solver * Solver ) validChar ( char rune ) ( valid bool ) {
2025-01-23 22:39:59 +01:00
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
}
2025-01-23 23:55:40 +01:00
2025-01-27 19:40:24 +01:00
func ( solver * Solver ) printUsage ( ) {
2025-01-23 23:55:40 +01:00
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 ( )
}