Bladeren bron

Accept commandline parameters.

Sacha Ligthert 1 jaar geleden
bovenliggende
commit
81edc8962d
6 gewijzigde bestanden met toevoegingen van 132 en 28 verwijderingen
  1. 9 1
      Taskfile.yml
  2. 0 4
      main.go
  3. 1 0
      solver/blocks.go
  4. 120 0
      solver/flags.go
  5. 0 3
      solver/processing.go
  6. 2 20
      solver/solver.go

+ 9 - 1
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:

+ 0 - 4
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()
 }

+ 1 - 0
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")

+ 120 - 0
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
+}

+ 0 - 3
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 {

+ 2 - 20
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()