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-21 21:32:50 +01:00
func ( solver * Solver ) populate_blocks ( ) {
2025-01-23 20:26:43 +01:00
defer solver . timeTrack ( time . Now ( ) , "Populated blocks" )
log . Println ( "Populating blocks" )
2025-01-21 21:32:50 +01:00
solver . find_blocks ( & solver . row1 , & solver . row1s )
solver . find_blocks ( & solver . row2 , & solver . row2s )
solver . find_blocks ( & solver . row3 , & solver . row3s )
solver . find_blocks ( & solver . row4 , & solver . row4s )
solver . find_blocks ( & solver . row5 , & solver . row5s )
solver . find_blocks ( & solver . row6 , & solver . row6s )
solver . find_blocks ( & solver . row7 , & solver . row7s )
solver . find_blocks ( & solver . row8 , & solver . row8s )
solver . find_blocks ( & solver . row9 , & solver . row9s )
2025-01-21 21:37:07 +01:00
// This calculates and stores the total number of solutions to validate.
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
}
2024-12-07 19:23:45 +01:00
func ( solver * Solver ) find_blocks ( row * string , rows * [ ] int ) {
// Declare selection
var selection [ ] int
var curr_blocks [ ] int
func_row := * row
for letter := range func_row {
if len ( selection ) == 0 {
curr_blocks = solver . blocks
} else {
curr_blocks = selection
selection = nil
}
for block := range curr_blocks {
curr_row := strconv . Itoa ( curr_blocks [ block ] )
if func_row [ letter ] == curr_row [ letter ] {
found_row , _ := strconv . Atoi ( curr_row )
selection = append ( selection , found_row )
}
if func_row [ letter ] == '0' {
found_row , _ := strconv . Atoi ( curr_row )
selection = append ( selection , found_row )
}
} // End for-loop
} // End for-loop
* rows = selection
}
func ( solver * Solver ) check_combinations ( ) {
for rows1_index := range solver . row1s {
for rows2_index := range solver . row2s {
for rows3_index := range solver . row3s {
for rows4_index := range solver . row4s {
for rows5_index := range solver . row5s {
for rows6_index := range solver . row6s {
for rows7_index := range solver . row7s {
for rows8_index := range solver . row8s {
2024-12-08 01:28:32 +01:00
for rows9_index := range solver . row9s {
go solver . routine_validator ( rows1_index , rows2_index , rows3_index , rows4_index , rows5_index , rows6_index , rows7_index , rows8_index , rows9_index )
}
2024-12-07 19:23:45 +01:00
}
}
}
}
}
}
}
}
}
func ( solver * Solver ) routine_validator ( rows1_index int , rows2_index int , rows3_index int , rows4_index int , rows5_index int , rows6_index int , rows7_index int , rows8_index int , rows9_index int ) {
2025-01-23 20:26:43 +01:00
solver . counter = solver . counter + 1
2024-12-07 19:23:45 +01:00
if solver . validate_combination ( solver . row1s [ rows1_index ] , solver . row2s [ rows2_index ] , solver . row3s [ rows3_index ] , solver . row4s [ rows4_index ] , solver . row5s [ rows5_index ] , solver . row6s [ rows6_index ] , solver . row7s [ rows7_index ] , solver . row8s [ rows8_index ] , solver . row9s [ rows9_index ] ) {
solver . solutions = append ( solver . solutions , solver . render_combination ( solver . row1s [ rows1_index ] , solver . row2s [ rows2_index ] , solver . row3s [ rows3_index ] , solver . row4s [ rows4_index ] , solver . row5s [ rows5_index ] , solver . row6s [ rows6_index ] , solver . row7s [ rows7_index ] , solver . row8s [ rows8_index ] , solver . row9s [ rows9_index ] ) )
}
2025-01-23 20:26:43 +01:00
}
func ( solver * Solver ) tracker ( ) {
defer solver . timeTrack ( time . Now ( ) , "Validated solutions" )
log . Println ( "Validating solutions" )
// Tracking percenting an progress
var percentage float32
var track int
// Tracking the rate
var rate_start int
var rate_stop int
var rate_diff int
// Tracking duration
var timer_start = time . Now ( )
// Prevent division-by-zero error when establishing `rate`
time . Sleep ( time . Second )
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
for solver . iter != solver . counter {
// Determine how far we are.
2024-12-07 19:23:45 +01:00
percentage = ( float32 ( solver . counter ) / ( float32 ( solver . iter ) / 100 ) )
2025-01-23 20:26:43 +01:00
if track <= int ( percentage ) {
// Reset the loop
rate_stop = int ( solver . counter )
rate_diff = rate_stop - rate_start
// Make sure something happened, making rate_start the only reliable variable
if rate_diff == 0 && rate_start > 1 {
percentage = 100
solver . counter = solver . iter
}
timer_elapsed := time . Since ( timer_start )
rate := int64 ( rate_diff ) / int64 ( timer_elapsed . Seconds ( ) )
// 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 {
est_fin = solver . secondsToHuman ( ( int ( solver . iter ) - int ( solver . counter ) ) / int ( rate ) )
}
// Printing the meat
log . Println ( "Processing: " + strconv . Itoa ( int ( percentage ) ) + "% (" + strconv . Itoa ( int ( solver . counter ) ) + "/" + strconv . Itoa ( int ( solver . iter ) ) + "); Rate (avg): " + strconv . Itoa ( int ( rate ) ) + "/sec for " + timer_elapsed . String ( ) + "; Time left (est.): " + est_fin )
// Wrap up the loop or break
if int ( percentage ) > track {
track = int ( percentage )
} else {
track = track + 1
}
rate_start = rate_stop
timer_start = time . Now ( )
if rate_diff == 0 && rate_start > 100 {
break
}
}
time . Sleep ( 1 * time . Second )
2024-12-07 19:23:45 +01:00
}
}
func ( solver * Solver ) validate_combination ( row1 int , row2 int , row3 int , row4 int , row5 int , row6 int , row7 int , row8 int , row9 int ) bool {
var retval bool
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
}