flags.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package solver
  2. import (
  3. "flag"
  4. "fmt"
  5. "log"
  6. "os"
  7. "runtime"
  8. )
  9. func (solver *Solver) parse_flags() {
  10. // Define variables
  11. var row1 string
  12. var row2 string
  13. var row3 string
  14. var row4 string
  15. var row5 string
  16. var row6 string
  17. var row7 string
  18. var row8 string
  19. var row9 string
  20. var split int
  21. var part int
  22. // Define parameters
  23. flag.StringVar(&row1, "row1", "000000000", "1st row of the sudoku puzzle.")
  24. flag.StringVar(&row2, "row2", "000000000", "2nd row of the sudoku puzzle.")
  25. flag.StringVar(&row3, "row3", "000000000", "4rd row of the sudoku puzzle.")
  26. flag.StringVar(&row4, "row4", "000000000", "4th row of the sudoku puzzle.")
  27. flag.StringVar(&row5, "row5", "000000000", "5th row of the sudoku puzzle.")
  28. flag.StringVar(&row6, "row6", "000000000", "6th row of the sudoku puzzle.")
  29. flag.StringVar(&row7, "row7", "000000000", "7th row of the sudoku puzzle.")
  30. flag.StringVar(&row8, "row8", "000000000", "8th row of the sudoku puzzle.")
  31. flag.StringVar(&row9, "row9", "000000000", "9th row of the sudoku puzzle.")
  32. flag.IntVar(&solver.numcpus, "numcpu", runtime.NumCPU(), "Number of CPU cores to assign to this task.")
  33. flag.IntVar(&split, "split", 1, "Split the tasks in n parts. This depends on the availability of the first row.")
  34. flag.IntVar(&part, "part", 1, "Process part x in n parts. Cannot be lower than 1, or higher than specified in split.")
  35. // Parse the flags
  36. flag.Parse()
  37. // Process any changes to the CPU usage.
  38. if solver.numcpus <= 0 {
  39. log.Printf("ERROR: Number of CPU cores must be 1 or higher.\n\n")
  40. solver.print_Usage()
  41. os.Exit(1)
  42. }
  43. if solver.numcpus != runtime.NumCPU() {
  44. runtime.GOMAXPROCS(solver.numcpus)
  45. }
  46. // Process rows
  47. if row1 == "000000000" || row2 == "000000000" || row3 == "000000000" || row4 == "000000000" || row5 == "000000000" || row6 == "000000000" || row7 == "000000000" || row8 == "000000000" || row9 == "000000000" {
  48. log.Printf("ERROR: All parameters must be entered.\n\n")
  49. solver.print_Usage()
  50. os.Exit(1)
  51. }
  52. // Validate the row (never trust user input)
  53. solver.validate_row("row1", row1)
  54. solver.validate_row("row2", row2)
  55. solver.validate_row("row3", row3)
  56. solver.validate_row("row4", row4)
  57. solver.validate_row("row5", row5)
  58. solver.validate_row("row6", row6)
  59. solver.validate_row("row7", row7)
  60. solver.validate_row("row8", row8)
  61. solver.validate_row("row9", row9)
  62. // Put entries in into the struct
  63. solver.row1 = row1
  64. solver.row2 = row2
  65. solver.row3 = row3
  66. solver.row4 = row4
  67. solver.row5 = row5
  68. solver.row6 = row6
  69. solver.row7 = row7
  70. solver.row8 = row8
  71. solver.row9 = row9
  72. // Process workload splitting
  73. // Ensure split and part are 1 or higher
  74. if split <= 0 || part <= 0 {
  75. log.Printf("ERROR: '-split' and '-part' need to be 1 or higher.\n")
  76. solver.print_Usage()
  77. os.Exit(1)
  78. }
  79. // Ensure part is between 1 and split
  80. if part > split {
  81. log.Printf("ERROR: '-part' cannot be bigger than `-split`.\n")
  82. solver.print_Usage()
  83. os.Exit(1)
  84. }
  85. solver.split = split
  86. solver.part = part
  87. }
  88. func (solver *Solver) validate_row(name string, row string) {
  89. var found bool
  90. var double bool
  91. count := make(map[rune]int)
  92. // 1. Make sure the row is 9 in length
  93. if len(row) != 9 {
  94. log.Printf("ERROR: Invalid length of %s (%s), must be 9 numbers\n\n", name, row)
  95. solver.print_Usage()
  96. os.Exit(1)
  97. }
  98. // 2. Ensure all digits are numbers
  99. for _, value := range row {
  100. found = solver.valid_char(value)
  101. }
  102. if !found {
  103. log.Printf("ERROR: Invalid character of %s (%s), must be 9 numbers\n\n", name, row)
  104. solver.print_Usage()
  105. os.Exit(1)
  106. }
  107. // 3. Ensure all digits (except zero) are there only once
  108. for _, digits := range row {
  109. count[digits] = count[digits] + 1
  110. }
  111. for key, value := range count {
  112. if value > 1 && key != 48 {
  113. double = true
  114. }
  115. }
  116. if double {
  117. log.Printf("ERROR: Double character of %s (%s), numbers between 1 and 9 may only be entered once\n\n", name, row)
  118. solver.print_Usage()
  119. os.Exit(1)
  120. }
  121. }
  122. func (solver *Solver) valid_char(char rune) bool {
  123. var valid bool
  124. decvals := [10]int{48, 49, 50, 51, 52, 53, 54, 55, 56, 57}
  125. for _, value := range decvals {
  126. if char == rune(value) {
  127. valid = true
  128. }
  129. }
  130. return valid
  131. }
  132. func (solver *Solver) print_Usage() {
  133. fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0])
  134. 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")
  135. fmt.Fprintf(flag.CommandLine.Output(), "Example: %s -row1 ... -row2 ... -row3 ... (etc)\n\n", os.Args[0])
  136. flag.PrintDefaults()
  137. }