2024-12-07 19:23:45 +01:00
package solver
import (
2025-01-21 21:43:27 +01:00
"log"
2024-12-07 19:23:45 +01:00
"strconv"
2025-01-23 20:26:43 +01:00
"time"
2024-12-07 19:23:45 +01:00
)
2025-01-27 21:47:35 +01:00
func ( solver * Solver ) PopulateBlocks ( ) {
2025-01-23 20:26:43 +01:00
defer solver . timeTrack ( time . Now ( ) , "Populated blocks" )
log . Println ( "Populating blocks" )
2025-01-27 21:47:35 +01:00
solver . findBlocks ( & solver . Row1 , & solver . row1s )
solver . findBlocks ( & solver . Row2 , & solver . row2s )
solver . findBlocks ( & solver . Row3 , & solver . row3s )
solver . findBlocks ( & solver . Row4 , & solver . row4s )
solver . findBlocks ( & solver . Row5 , & solver . row5s )
solver . findBlocks ( & solver . Row6 , & solver . row6s )
solver . findBlocks ( & solver . Row7 , & solver . row7s )
solver . findBlocks ( & solver . Row8 , & solver . row8s )
solver . findBlocks ( & solver . Row9 , & solver . row9s )
2025-01-21 21:37:07 +01:00
// This calculates and stores the total number of solutions to validate.
2025-01-27 21:47:35 +01:00
solver . Iter = int64 ( len ( solver . row1s ) ) * int64 ( len ( solver . row2s ) ) * int64 ( len ( solver . row3s ) ) * int64 ( len ( solver . row4s ) ) * int64 ( len ( solver . row5s ) ) * int64 ( len ( solver . row6s ) ) * int64 ( len ( solver . row7s ) ) * int64 ( len ( solver . row8s ) ) * int64 ( len ( solver . row9s ) )
2025-01-23 20:26:43 +01:00
2025-01-21 21:32:50 +01:00
}
2025-01-27 19:40:24 +01:00
func ( solver * Solver ) findBlocks ( row * string , rows * [ ] int ) {
2024-12-07 19:23:45 +01:00
// Declare selection
var selection [ ] int
2025-01-27 19:40:24 +01:00
var currBlocks [ ] int
funcRow := * row
2024-12-07 19:23:45 +01:00
2025-01-27 19:40:24 +01:00
for letter := range funcRow {
2024-12-07 19:23:45 +01:00
if len ( selection ) == 0 {
2025-01-27 19:40:24 +01:00
currBlocks = solver . blocks
2024-12-07 19:23:45 +01:00
} else {
2025-01-27 19:40:24 +01:00
currBlocks = selection
2024-12-07 19:23:45 +01:00
selection = nil
}
2025-01-27 19:40:24 +01:00
for _ , block := range currBlocks {
2024-12-07 19:23:45 +01:00
2025-01-27 19:40:24 +01:00
currRow := strconv . Itoa ( block )
2024-12-07 19:23:45 +01:00
2025-01-27 19:40:24 +01:00
if funcRow [ letter ] == currRow [ letter ] {
foundRow , _ := strconv . Atoi ( currRow )
selection = append ( selection , foundRow )
2024-12-07 19:23:45 +01:00
}
2025-01-27 19:40:24 +01:00
if funcRow [ letter ] == '0' {
foundRow , _ := strconv . Atoi ( currRow )
selection = append ( selection , foundRow )
2024-12-07 19:23:45 +01:00
}
} // End for-loop
} // End for-loop
* rows = selection
}
2025-01-27 21:47:35 +01:00
func ( solver * Solver ) CheckCombinations ( ) {
2025-01-27 19:40:24 +01:00
for rows1Index := range solver . row1s {
for rows2Index := range solver . row2s {
for rows3Index := range solver . row3s {
for rows4Index := range solver . row4s {
for rows5Index := range solver . row5s {
for rows6Index := range solver . row6s {
for rows7Index := range solver . row7s {
for rows8Index := range solver . row8s {
for rows9Index := range solver . row9s {
2025-01-27 22:40:13 +01:00
go solver . validator ( rows1Index , rows2Index , rows3Index , rows4Index , rows5Index , rows6Index , rows7Index , rows8Index , rows9Index )
2024-12-08 01:28:32 +01:00
}
2024-12-07 19:23:45 +01:00
}
}
}
}
}
}
}
}
}
2025-01-27 22:40:13 +01:00
func ( solver * Solver ) validator ( rows1Index int , rows2Index int , rows3Index int , rows4Index int , rows5Index int , rows6Index int , rows7Index int , rows8Index int , rows9Index int ) {
2024-12-07 19:23:45 +01:00
2025-01-25 19:08:31 +01:00
solver . counter . Add ( 1 )
2024-12-07 19:23:45 +01:00
2025-01-27 19:40:24 +01:00
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 ] ) {
solver . solutions = append ( solver . solutions , solver . renderCombination ( 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 ] ) )
2024-12-07 19:23:45 +01:00
}
2025-01-23 20:26:43 +01:00
}
2025-01-27 21:47:35 +01:00
func ( solver * Solver ) Tracker ( ) {
2025-01-23 20:26:43 +01:00
2025-01-27 22:40:13 +01:00
// Add time tracking
2025-01-23 20:26:43 +01:00
defer solver . timeTrack ( time . Now ( ) , "Validated solutions" )
log . Println ( "Validating solutions" )
2025-01-25 17:32:11 +01:00
// Determine if the main-loop is done
var done bool
// Tracking progress in percentages
2025-01-23 20:26:43 +01:00
var percentage float32
2025-01-25 17:32:11 +01:00
// Tracking progress in validated solutions
2025-01-23 20:26:43 +01:00
var track int
2025-01-25 17:32:11 +01:00
// Tracking the rate, starting point
2025-01-27 19:40:24 +01:00
var rateStart int64
2025-01-25 17:32:11 +01:00
// Tracking the rate, difference between previous iterations
2025-01-27 19:40:24 +01:00
var rateDiff int64
2025-01-23 20:26:43 +01:00
// Tracking duration
2025-01-27 19:40:24 +01:00
var timerStart = time . Now ( )
2024-12-07 19:23:45 +01:00
2025-01-23 20:26:43 +01:00
// Estimation how long it will take
var est_fin string
2025-01-27 21:47:35 +01:00
// While not needed for rateDiff anymore, it makes estimation calculations more accurate. ☹️
time . Sleep ( time . Second )
// for solver.Iter != solver.counter { // Start for-loop
2025-01-25 17:32:11 +01:00
for ! done {
2025-01-23 20:26:43 +01:00
// Determine how far we are.
2025-01-27 21:47:35 +01:00
percentage = ( float32 ( solver . counter . Load ( ) ) / ( float32 ( solver . Iter ) / 100 ) )
2025-01-25 17:32:11 +01:00
// Reset the loop
2025-01-27 19:40:24 +01:00
rateDiff = solver . counter . Load ( ) - rateStart
2025-01-25 17:32:11 +01:00
2025-01-27 19:40:24 +01:00
if track <= int ( percentage ) || rateDiff == 0 { // Start if-statement
2025-01-23 20:26:43 +01:00
2025-01-27 19:40:24 +01:00
// Make sure something happened, making rateStart the only reliable variable
2025-01-27 21:47:35 +01:00
if solver . Iter == solver . counter . Load ( ) {
2025-01-23 20:26:43 +01:00
percentage = 100
2025-01-27 21:47:35 +01:00
solver . counter . Store ( solver . Iter )
2025-01-25 17:32:11 +01:00
done = true
2025-01-23 20:26:43 +01:00
}
2025-01-27 19:40:24 +01:00
timer_elapsed := time . Since ( timerStart )
solver . rates = append ( solver . rates , rateDiff )
rate_avg := solver . calcAVG ( )
2025-01-23 20:26:43 +01:00
2025-01-25 14:34:51 +01:00
// Estimate when this is finished
2025-01-27 19:40:24 +01:00
if rateDiff == 0 {
2025-01-23 20:26:43 +01:00
est_fin = "N/A"
} else {
2025-01-27 21:47:35 +01:00
duration_int := ( solver . Iter - solver . counter . Load ( ) ) / rate_avg
2025-01-27 19:20:49 +01:00
duration_string := strconv . Itoa ( int ( duration_int ) ) + "s"
est , err := time . ParseDuration ( duration_string )
if err != nil {
est_fin = "parse error"
}
est_fin = est . String ( )
2025-01-23 20:26:43 +01:00
}
2025-01-25 17:32:11 +01:00
// Printing the progress
2025-01-27 21:47:35 +01:00
log . Println ( "Processing: " + strconv . Itoa ( int ( percentage ) ) + "% (" + strconv . FormatInt ( solver . counter . Load ( ) , 10 ) + "/" + strconv . Itoa ( int ( solver . Iter ) ) + "); Rate: " + strconv . FormatInt ( rateDiff , 10 ) + "/sec for " + timer_elapsed . String ( ) + "; Time left (est.): " + est_fin )
2025-01-23 20:26:43 +01:00
2025-01-25 17:32:11 +01:00
// After we are done printing, exit this for-loop
if percentage == 100 {
break
}
2025-01-23 20:26:43 +01:00
// Wrap up the loop or break
if int ( percentage ) > track {
track = int ( percentage )
} else {
track = track + 1
}
2025-01-27 19:40:24 +01:00
timerStart = time . Now ( )
2025-01-23 20:26:43 +01:00
}
2025-01-25 17:32:11 +01:00
// Resert the rate counter
2025-01-27 19:40:24 +01:00
rateStart = solver . counter . Load ( )
2025-01-25 17:54:18 +01:00
2025-01-25 17:32:11 +01:00
// Sleep for a second
2025-01-27 21:47:35 +01:00
if solver . Iter != solver . counter . Load ( ) {
2025-01-27 20:17:09 +01:00
time . Sleep ( 1 * time . Second )
}
2025-01-25 17:32:11 +01:00
} // End for-loop
2024-12-07 19:23:45 +01:00
}
2025-01-27 19:40:24 +01:00
func ( solver * Solver ) validateCombination ( row1 int , row2 int , row3 int , row4 int , row5 int , row6 int , row7 int , row8 int , row9 int ) ( retval bool ) {
2024-12-07 19:23:45 +01:00
retval = true
row1s := strconv . Itoa ( row1 )
row2s := strconv . Itoa ( row2 )
row3s := strconv . Itoa ( row3 )
row4s := strconv . Itoa ( row4 )
row5s := strconv . Itoa ( row5 )
row6s := strconv . Itoa ( row6 )
row7s := strconv . Itoa ( row7 )
row8s := strconv . Itoa ( row8 )
row9s := strconv . Itoa ( row9 )
for index := range 9 {
if row1s [ index ] == row2s [ index ] || row1s [ index ] == row3s [ index ] || row1s [ index ] == row4s [ index ] || row1s [ index ] == row5s [ index ] || row1s [ index ] == row6s [ index ] || row1s [ index ] == row7s [ index ] || row1s [ index ] == row8s [ index ] || row1s [ index ] == row9s [ index ] {
retval = false
}
if row2s [ index ] == row1s [ index ] || row2s [ index ] == row3s [ index ] || row2s [ index ] == row4s [ index ] || row2s [ index ] == row5s [ index ] || row2s [ index ] == row6s [ index ] || row2s [ index ] == row7s [ index ] || row2s [ index ] == row8s [ index ] || row2s [ index ] == row9s [ index ] {
retval = false
}
if row3s [ index ] == row1s [ index ] || row3s [ index ] == row2s [ index ] || row3s [ index ] == row4s [ index ] || row3s [ index ] == row5s [ index ] || row3s [ index ] == row6s [ index ] || row3s [ index ] == row7s [ index ] || row3s [ index ] == row8s [ index ] || row3s [ index ] == row9s [ index ] {
retval = false
}
if row4s [ index ] == row1s [ index ] || row4s [ index ] == row2s [ index ] || row4s [ index ] == row3s [ index ] || row4s [ index ] == row5s [ index ] || row4s [ index ] == row6s [ index ] || row4s [ index ] == row7s [ index ] || row4s [ index ] == row8s [ index ] || row4s [ index ] == row9s [ index ] {
retval = false
}
if row5s [ index ] == row1s [ index ] || row5s [ index ] == row2s [ index ] || row5s [ index ] == row3s [ index ] || row5s [ index ] == row4s [ index ] || row5s [ index ] == row6s [ index ] || row5s [ index ] == row7s [ index ] || row5s [ index ] == row8s [ index ] || row5s [ index ] == row9s [ index ] {
retval = false
}
if row6s [ index ] == row1s [ index ] || row6s [ index ] == row2s [ index ] || row6s [ index ] == row3s [ index ] || row6s [ index ] == row4s [ index ] || row6s [ index ] == row5s [ index ] || row6s [ index ] == row7s [ index ] || row6s [ index ] == row8s [ index ] || row6s [ index ] == row9s [ index ] {
retval = false
}
if row7s [ index ] == row1s [ index ] || row7s [ index ] == row2s [ index ] || row7s [ index ] == row3s [ index ] || row7s [ index ] == row4s [ index ] || row5s [ index ] == row6s [ index ] || row7s [ index ] == row6s [ index ] || row7s [ index ] == row8s [ index ] || row7s [ index ] == row9s [ index ] {
retval = false
}
if row8s [ index ] == row1s [ index ] || row8s [ index ] == row2s [ index ] || row8s [ index ] == row3s [ index ] || row8s [ index ] == row4s [ index ] || row8s [ index ] == row5s [ index ] || row8s [ index ] == row6s [ index ] || row8s [ index ] == row7s [ index ] || row8s [ index ] == row9s [ index ] {
retval = false
}
if row9s [ index ] == row1s [ index ] || row9s [ index ] == row2s [ index ] || row9s [ index ] == row3s [ index ] || row9s [ index ] == row4s [ index ] || row9s [ index ] == row5s [ index ] || row9s [ index ] == row6s [ index ] || row9s [ index ] == row7s [ index ] || row9s [ index ] == row8s [ index ] {
retval = false
}
}
return retval
}
2025-01-25 14:34:51 +01:00
2025-01-27 19:40:24 +01:00
func ( solver * Solver ) calcAVG ( ) ( avg int64 ) {
var avgSum int64
2025-01-25 14:34:51 +01:00
for _ , value := range solver . rates {
2025-01-27 19:40:24 +01:00
avgSum += value
2025-01-25 14:34:51 +01:00
}
2025-01-27 19:40:24 +01:00
avg = avgSum / int64 ( len ( solver . rates ) )
2025-01-25 14:34:51 +01:00
2025-01-25 17:54:18 +01:00
return
2025-01-25 14:34:51 +01:00
}