processing.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. package solver
  2. import (
  3. "log"
  4. "strconv"
  5. "time"
  6. )
  7. // Find all possible blocks that can be used to find a solution.
  8. func (solver *Solver) PopulateBlocks() {
  9. defer solver.timeTrack(time.Now(), "Populated blocks")
  10. log.Println("Populating blocks")
  11. solver.findBlocks(&solver.Controller.Row1, &solver.row1s)
  12. solver.findBlocks(&solver.Controller.Row2, &solver.row2s)
  13. solver.findBlocks(&solver.Controller.Row3, &solver.row3s)
  14. solver.findBlocks(&solver.Controller.Row4, &solver.row4s)
  15. solver.findBlocks(&solver.Controller.Row5, &solver.row5s)
  16. solver.findBlocks(&solver.Controller.Row6, &solver.row6s)
  17. solver.findBlocks(&solver.Controller.Row7, &solver.row7s)
  18. solver.findBlocks(&solver.Controller.Row8, &solver.row8s)
  19. solver.findBlocks(&solver.Controller.Row9, &solver.row9s)
  20. // This calculates and stores the total number of solutions to validate.
  21. solver.Iter = uint64(len(solver.row1s)) * uint64(len(solver.row2s)) * uint64(len(solver.row3s)) * uint64(len(solver.row4s)) * uint64(len(solver.row5s)) * uint64(len(solver.row6s)) * uint64(len(solver.row7s)) * uint64(len(solver.row8s)) * uint64(len(solver.row9s))
  22. }
  23. // The actual function that finds the blocks matching the partial blocks.
  24. func (solver *Solver) findBlocks(row *string, rows *[]string) {
  25. // Declare selection
  26. var selection []string
  27. var currBlocks []string
  28. funcRow := *row
  29. for letter := range funcRow {
  30. if len(selection) == 0 {
  31. currBlocks = solver.Controller.Blocks
  32. } else {
  33. currBlocks = selection
  34. selection = nil
  35. }
  36. for _, block := range currBlocks {
  37. currRow := block
  38. if funcRow[letter] == currRow[letter] {
  39. foundRow := currRow
  40. selection = append(selection, foundRow)
  41. }
  42. if funcRow[letter] == '0' {
  43. foundRow := currRow
  44. selection = append(selection, foundRow)
  45. }
  46. } // End for-loop
  47. } // End for-loop
  48. *rows = selection
  49. }
  50. // Iterate through all combination of blocks and validate them.
  51. func (solver *Solver) CheckCombinations() {
  52. for rows1Index := range solver.row1s {
  53. for rows2Index := range solver.row2s {
  54. for rows3Index := range solver.row3s {
  55. for rows4Index := range solver.row4s {
  56. for rows5Index := range solver.row5s {
  57. for rows6Index := range solver.row6s {
  58. for rows7Index := range solver.row7s {
  59. for rows8Index := range solver.row8s {
  60. for rows9Index := range solver.row9s {
  61. go solver.validator(rows1Index, rows2Index, rows3Index, rows4Index, rows5Index, rows6Index, rows7Index, rows8Index, rows9Index)
  62. }
  63. }
  64. }
  65. }
  66. }
  67. }
  68. }
  69. }
  70. }
  71. }
  72. // Validate the provided rows and verify it is a valid solution.
  73. func (solver *Solver) validator(rows1Index int, rows2Index int, rows3Index int, rows4Index int, rows5Index int, rows6Index int, rows7Index int, rows8Index int, rows9Index int) {
  74. solver.counter.Add(1)
  75. if solver.validateCombination(solver.row1s[rows1Index], solver.row2s[rows2Index], solver.row3s[rows3Index], solver.row4s[rows4Index], solver.row5s[rows5Index], solver.row6s[rows6Index], solver.row7s[rows7Index], solver.row8s[rows8Index], solver.row9s[rows9Index]) {
  76. solver.Controller.Solutions = append(solver.Controller.Solutions, []string{solver.row1s[rows1Index], solver.row2s[rows2Index], solver.row3s[rows3Index], solver.row4s[rows4Index], solver.row5s[rows5Index], solver.row6s[rows6Index], solver.row7s[rows7Index], solver.row8s[rows8Index], solver.row9s[rows9Index]})
  77. }
  78. }
  79. // Keep track and output progress.
  80. // Calculate rates, display percentages, estimate the ETA till completion.
  81. func (solver *Solver) Tracker() {
  82. // Add time tracking
  83. defer solver.timeTrack(time.Now(), "Validated solutions")
  84. log.Println("Validating solutions")
  85. // Determine if the main-loop is done
  86. var done bool
  87. // Tracking progress in percentages
  88. var percentage float32
  89. // Tracking progress in validated solutions
  90. var track int
  91. // Tracking the rate, starting point
  92. var rateStart uint64
  93. // Tracking the rate, difference between previous iterations
  94. var rateDiff uint64
  95. // Tracking duration
  96. var timerStart = time.Now()
  97. // Estimation how long it will take
  98. var est_fin string
  99. // While not needed for rateDiff anymore, it makes estimation calculations more accurate. ☹️
  100. time.Sleep(time.Second)
  101. // for solver.Iter != solver.counter { // Start for-loop
  102. for !done {
  103. // Determine how far we are.
  104. percentage = (float32(solver.counter.Load()) / (float32(solver.Iter) / 100))
  105. // Reset the loop
  106. rateDiff = solver.counter.Load() - rateStart
  107. if track <= int(percentage) || rateDiff == 0 { // Start if-statement
  108. // Make sure something happened, making rateStart the only reliable variable
  109. if solver.Iter == solver.counter.Load() {
  110. percentage = 100
  111. solver.counter.Store(solver.Iter)
  112. done = true
  113. }
  114. timer_elapsed := time.Since(timerStart)
  115. solver.rates = append(solver.rates, rateDiff)
  116. rate_avg := solver.calcAVG()
  117. // Estimate when this is finished
  118. if rateDiff == 0 {
  119. est_fin = "N/A"
  120. } else {
  121. duration_int := (solver.Iter - solver.counter.Load()) / rate_avg
  122. duration_string := strconv.Itoa(int(duration_int)) + "s"
  123. est, err := time.ParseDuration(duration_string)
  124. if err != nil {
  125. est_fin = "parse error"
  126. } else {
  127. est_fin = est.String()
  128. }
  129. }
  130. // Printing the progress
  131. log.Println("Processing: " + strconv.Itoa(int(percentage)) + "% (" + strconv.FormatUint(solver.counter.Load(), 10) + "/" + strconv.Itoa(int(solver.Iter)) + "); Rate: " + strconv.FormatUint(rateDiff, 10) + "/sec for " + timer_elapsed.String() + "; Time left (est.): " + est_fin)
  132. // After we are done printing, exit this for-loop
  133. if percentage == 100 {
  134. break
  135. }
  136. // Wrap up the loop or break
  137. if int(percentage) > track {
  138. track = int(percentage)
  139. } else {
  140. track = track + 1
  141. }
  142. timerStart = time.Now()
  143. }
  144. // Resert the rate counter
  145. rateStart = solver.counter.Load()
  146. // Sleep for a second
  147. if solver.Iter != solver.counter.Load() {
  148. time.Sleep(1 * time.Second)
  149. }
  150. } // End for-loop
  151. }
  152. // Validate combination
  153. func (solver *Solver) validateCombination(row1 string, row2 string, row3 string, row4 string, row5 string, row6 string, row7 string, row8 string, row9 string) (retval bool) {
  154. retval = true
  155. for index := range 9 {
  156. if row1[index] == row2[index] || row1[index] == row3[index] || row1[index] == row4[index] || row1[index] == row5[index] || row1[index] == row6[index] || row1[index] == row7[index] || row1[index] == row8[index] || row1[index] == row9[index] {
  157. retval = false
  158. }
  159. if row2[index] == row1[index] || row2[index] == row3[index] || row2[index] == row4[index] || row2[index] == row5[index] || row2[index] == row6[index] || row2[index] == row7[index] || row2[index] == row8[index] || row2[index] == row9[index] {
  160. retval = false
  161. }
  162. if row3[index] == row1[index] || row3[index] == row2[index] || row3[index] == row4[index] || row3[index] == row5[index] || row3[index] == row6[index] || row3[index] == row7[index] || row3[index] == row8[index] || row3[index] == row9[index] {
  163. retval = false
  164. }
  165. if row4[index] == row1[index] || row4[index] == row2[index] || row4[index] == row3[index] || row4[index] == row5[index] || row4[index] == row6[index] || row4[index] == row7[index] || row4[index] == row8[index] || row4[index] == row9[index] {
  166. retval = false
  167. }
  168. if row5[index] == row1[index] || row5[index] == row2[index] || row5[index] == row3[index] || row5[index] == row4[index] || row5[index] == row6[index] || row5[index] == row7[index] || row5[index] == row8[index] || row5[index] == row9[index] {
  169. retval = false
  170. }
  171. if row6[index] == row1[index] || row6[index] == row2[index] || row6[index] == row3[index] || row6[index] == row4[index] || row6[index] == row5[index] || row6[index] == row7[index] || row6[index] == row8[index] || row6[index] == row9[index] {
  172. retval = false
  173. }
  174. if row7[index] == row1[index] || row7[index] == row2[index] || row7[index] == row3[index] || row7[index] == row4[index] || row5[index] == row6[index] || row7[index] == row6[index] || row7[index] == row8[index] || row7[index] == row9[index] {
  175. retval = false
  176. }
  177. if row8[index] == row1[index] || row8[index] == row2[index] || row8[index] == row3[index] || row8[index] == row4[index] || row8[index] == row5[index] || row8[index] == row6[index] || row8[index] == row7[index] || row8[index] == row9[index] {
  178. retval = false
  179. }
  180. if row9[index] == row1[index] || row9[index] == row2[index] || row9[index] == row3[index] || row9[index] == row4[index] || row9[index] == row5[index] || row9[index] == row6[index] || row9[index] == row7[index] || row9[index] == row8[index] {
  181. retval = false
  182. }
  183. }
  184. return retval
  185. }
  186. // Calculate the average rate in a stored slice of rates.
  187. func (solver *Solver) calcAVG() (avg uint64) {
  188. var avgSum uint64
  189. for _, value := range solver.rates {
  190. avgSum += uint64(value)
  191. }
  192. avg = avgSum / uint64(len(solver.rates))
  193. return
  194. }