parse.go 4.5 KB

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