From 81edc8962d0cd60f33d2441fd0b297f1e605c164 Mon Sep 17 00:00:00 2001 From: Sacha Ligthert Date: Thu, 23 Jan 2025 22:39:59 +0100 Subject: [PATCH] Accept commandline parameters. --- Taskfile.yml | 10 +++- main.go | 4 -- solver/blocks.go | 1 + solver/flags.go | 120 +++++++++++++++++++++++++++++++++++++++++++ solver/processing.go | 3 -- solver/solver.go | 22 +------- 6 files changed, 132 insertions(+), 28 deletions(-) create mode 100644 solver/flags.go diff --git a/Taskfile.yml b/Taskfile.yml index 0b6d6bc..b546800 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -5,7 +5,15 @@ version: '3' tasks: default: cmds: - - go run . + - go run . --help + silent: true + run_short: + cmds: + - go run . -row1 769104802 -row2 154800060 -row3 832700154 -row4 600900328 -row5 045328670 -row6 328670945 -row7 597410280 -row8 006283090 -row9 200590006 + silent: true + run_long: + cmds: + - go run . -row1 769104802 -row2 154800060 -row3 002700150 -row4 600900308 -row5 045328670 -row6 328670945 -row7 597410280 -row8 006283090 -row9 200590006 silent: true precommit: cmds: diff --git a/main.go b/main.go index 30d2454..21a09e0 100644 --- a/main.go +++ b/main.go @@ -5,10 +5,6 @@ import ( ) func main() { - - // Set global logger parameters - // log.SetFlags(log.LstdFlags | log.Lshortfile) - // Run the meat of the program solver.Run() } diff --git a/solver/blocks.go b/solver/blocks.go index 0396da2..5d062a2 100644 --- a/solver/blocks.go +++ b/solver/blocks.go @@ -9,6 +9,7 @@ import ( "time" ) +// TODO: Import at compile time, provide with the binary func (solver *Solver) load_blocks() { defer solver.timeTrack(time.Now(), "Loaded blocks") diff --git a/solver/flags.go b/solver/flags.go new file mode 100644 index 0000000..e27502b --- /dev/null +++ b/solver/flags.go @@ -0,0 +1,120 @@ +package solver + +import ( + "flag" + "fmt" + "log" + "os" +) + +func (solver *Solver) parse_flags() { + + // 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 + + // 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.") + + // Print additional help data + flag.Usage = func() { + fmt.Fprintf(flag.CommandLine.Output(), "Usages 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() + } + + // Parse the flags + flag.Parse() + + // Validate the row (never trust user input) + solver.validate_row("row1", row1) + solver.validate_row("row2", row2) + solver.validate_row("row3", row3) + solver.validate_row("row4", row4) + solver.validate_row("row5", row5) + solver.validate_row("row6", row6) + solver.validate_row("row7", row7) + solver.validate_row("row8", row8) + solver.validate_row("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 + +} + +func (solver *Solver) validate_row(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", name, row) + os.Exit(1) + } + + // 2. Ensure all digits are numbers + for _, value := range row { + found = solver.valid_char(value) + } + + if !found { + log.Printf("ERROR: Invalid character of %s; %s must be 9 numbers", name, row) + 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", name, row) + os.Exit(1) + } + +} + +func (solver *Solver) valid_char(char rune) bool { + var 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 +} diff --git a/solver/processing.go b/solver/processing.go index 20a0f94..85e08a9 100644 --- a/solver/processing.go +++ b/solver/processing.go @@ -135,9 +135,6 @@ func (solver *Solver) tracker() { // Estimate when this is finished: // TODO: Make this Bayesian - // TODO: Fix - // For short running solutions this is fine - // For long running solutions this breaks if rate_diff == 0 { est_fin = "N/A" } else { diff --git a/solver/solver.go b/solver/solver.go index 552a749..3bba782 100644 --- a/solver/solver.go +++ b/solver/solver.go @@ -8,26 +8,8 @@ func Run() { // Instantiate the Solver interface solver := Solver{} - // TODO: Move to args - solver.row1 = "769104802" - solver.row2 = "154800060" - solver.row3 = "002700150" - solver.row4 = "600900308" - solver.row5 = "045328670" - solver.row6 = "328670945" - solver.row7 = "597410280" - solver.row8 = "006283090" - solver.row9 = "200590006" - - solver.row1 = "769104802" - solver.row2 = "154800060" - solver.row3 = "832700154" - solver.row4 = "600900328" - solver.row5 = "045328670" - solver.row6 = "328670945" - solver.row7 = "597410280" - solver.row8 = "006283090" - solver.row9 = "200590006" + // Parse and handle flags + solver.parse_flags() // Load blocks from CSV file solver.load_blocks()