qazwsx Posted August 23, 2007 Share Posted August 23, 2007 (edited) This solver can solve any sudoku as long as it is possible. Input the numbers and then click solve. It uses 2 simple solving methods and then a brute force method. Comments and suggestions are welcome.V2: Can now recognize pairs. For a descritption of pairs Is faster than the first version for most puzzles.V2.1: now has naked pairs for cells as wellNow has a updated Gui and a clear button Thx to Piano_man for the guiCODE#include <GuiConstants.au3>Global $constant[10][10] ;user numbers [row-1][column]Global $input[10][10] ;input boxes [row-1][column]Global $1Global $2Global $3Global $rGlobal $cGlobal $possibilities[10][10][10] ;[row][column][number] 1 = applicable 0 or "" = notGlobal $change ;change in testsHotKeySet("{esc}", "_exit")$Form1_1 = GUICreate("solver", 610, 374, 189, 173)$Button1 = GUICtrlCreateButton("Solve", 260, 338, 75, 25, 0)$Button2 = GUICtrlCreateButton("Clear", 32, 336, 75, 25, 0)$XaddAmmount = 0$YaddAmmount = 0GUISetFont(11)For $i = 0 To 8 If $i = 3 Or $i = 6 Or $i = 9 Then $YaddAmmount += 15 EndIf For $j = 1 To 9 $x = 56 * $j - 60 $y = 32 * ($i + 1) - 10 If Mod($j - 1, 3) = 0 Then $XaddAmmount += 30 EndIf $input[$i][$j] = GUICtrlCreateInput("", $x + $XaddAmmount, $y + $YaddAmmount, 36, 23, $ES_CENTER) Next $XaddAmmount = 0NextGUISetState(@SW_SHOW);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;_sigletoncolumn cell check problemWhile 1 $nMsg = GUIGetMsg() Switch $nMsg Case - 3 Exit Case $Button1 _record() _allpossible() _testpossible() _solver2() MsgBox(0, "Solved", "Puzzle Solved") Case $Button2 _clear() EndSwitchWEndFunc _record() For $i = 1 To 9 For $j = 1 To 9 $constant[$i][$j] = GUICtrlRead($input[$i - 1][$j]) Next NextEndFunc ;==>_recordFunc _rowcheck($row, $column) For $i = 1 To 9 If $i <> $column Then If StringCompare(GUICtrlRead($input[$row - 1][$column]), GUICtrlRead($input[$row - 1][$i])) = 0 Then Return 1 EndIf NextEndFunc ;==>_rowcheckFunc _columncheck($row, $column) For $i = 1 To 9 If $i <> $row Then If StringCompare(GUICtrlRead($input[$row - 1][$column]), GUICtrlRead($input[$i - 1][$column])) = 0 Then Return 1 EndIf NextEndFunc ;==>_columncheckFunc _brutetest() For $r = 1 To 9 ;row For $c = 1 To 9 ;column If $constant[$r][$c] = "" Then For $n = 1 To 9 ;number to test GUICtrlSetData($input[$r - 1][$c], $n) $1 = _rowcheck($r, $c) $2 = _columncheck($r, $c) $3 = _cellcheck($r, $c) If $1 = 0 And $2 = 0 And $3 = 0 Then ExitLoop Next ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Back track If $1 = 1 Or $2 = 1 Or $3 = 1 Then While 1 GUICtrlSetData($input[$r - 1][$c], $constant[$r][$c]) $c = $c - 1 If $c < 1 Then $c = 9 $r = $r - 1 EndIf If $constant[$r][$c] <> "" Then Else While 1 $back = GUICtrlRead($input[$r - 1][$c]) If $back = "" Then $back = 0 $back = $back + 1 If $back = 10 Then ExitLoop EndIf GUICtrlSetData($input[$r - 1][$c], $back) $1 = _rowcheck($r, $c) $2 = _columncheck($r, $c) $3 = _cellcheck($r, $c) If $1 = 0 And $2 = 0 And $3 = 0 Then ExitLoop (2) WEnd EndIf WEnd EndIf ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EndIf Next NextEndFunc ;==>_brutetestFunc _cellcheck($row, $column) $row = $row - 1 $cellpos_row = Floor($row / 3) ; If $row= 0, 1, 2 then this=0, if $row= 3,4,5 then this=1, if $row= 6,7,8 then this=2 $cellpos_col = Floor(($column - 1) / 3) ; If $column= 1,2,3 then this=0, etc.. For $i = 3 * $cellpos_row To 3 * $cellpos_row + 2 ; (0 to 2) or (3 to 5) or (6 to 8) For $j = 3 * $cellpos_col + 1 To 3 * $cellpos_col + 3 ; (1 to 3) or (4 to 6) or (7 to 9) If $i <> $row Or $j <> $column Then If StringCompare(GUICtrlRead($input[$row][$column]), GUICtrlRead($input[$i][$j])) = 0 Then Return 1 EndIf Next NextEndFunc ;==>_cellcheckFunc _randomcheck() While 1 For $t = 0 To 8 For $l = 1 To 9 If $constant[$t][$l] = "" Then GUICtrlSetData($input[$t][$l], Random(1, 9, 1)) EndIf Next Next For $q = 1 To 9 For $z = 1 To 9 If _rowcheck($q, $z) = 1 Or _columncheck($q, $z) = 1 Or _cellcheck($q, $z) = 1 Then ExitLoop (2) Next Next If _rowcheck($q, $z) = 0 And _columncheck($q, $z) = 0 And _cellcheck($q, $z) = 0 Then ExitLoop (1) WEnd EndFunc ;==>_randomcheck;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; using possibilites arrayFunc _possible($row, $column) ;finds possible entries for a given box For $k = 1 To 9 ;numbers If $constant[$row][$column] = "" Then GUICtrlSetData($input[$row - 1][$column], $k) If _rowcheck($row, $column) = 0 And _columncheck($row, $column) = 0 And _cellcheck($row, $column) = 0 Then $possibilities[$row][$column][$k] = 1 Else $possibilities[$row][$column][$k] = 0 EndIf GUICtrlSetData($input[$row - 1][$column], "") EndIf NextEndFunc ;==>_possibleFunc _singlepossible($row, $column) Dim $count Dim $answer $count = 0 If $constant[$row][$column] = "" Then For $d = 1 To 9 If $possibilities[$row][$column][$d] = 1 Then $count = $count + 1 $answer = $d EndIf Next If $count = 1 Then GUICtrlSetData($input[$row - 1][$column], $answer) $constant[$row][$column] = $answer Return 1 EndIf EndIfEndFunc ;==>_singlepossibleFunc _singletoncolumn($column) Dim $count Dim $answer Dim $row For $d = 1 To 9 ;number $count = 0 For $a = 1 To 9 ;row If $constant[$a][$column] = "" Then If $possibilities[$a][$column][$d] = 1 Then $count = $count + 1 $row = $a EndIf EndIf Next If $count = 1 Then $answer = $d GUICtrlSetData($input[$row - 1][$column], $answer) $constant[$row][$column] = $answer Return $row ExitLoop EndIf NextEndFunc ;==>_singletoncolumnFunc _singletonrow($row) Dim $count Dim $answer Dim $column For $d = 1 To 9 ;number $count = 0 For $a = 1 To 9 ;column If $constant[$row][$a] = "" Then If $possibilities[$row][$a][$d] = 1 Then $count = $count + 1 $column = $a EndIf EndIf Next If $count = 1 Then $answer = $d GUICtrlSetData($input[$row - 1][$column], $answer) $constant[$row][$column] = $answer Return $column ExitLoop EndIf NextEndFunc ;==>_singletonrowFunc _possiblerow($row1) ;updates possibilites for row For $p = 1 To 9 ;column If $constant[$row1][$p] = "" Then _possible($row1, $p) EndIf NextEndFunc ;==>_possiblerowFunc _possiblecolumn($column1) ; updates possibilities for column For $p = 1 To 9 ;row If $constant[$p][$column1] = "" Then _possible($p, $column1) EndIf NextEndFunc ;==>_possiblecolumnFunc _possiblecell($row1, $column1) ;updates all possibilities for a cell containging the given box If $constant[$row1][$column1] = "" Then $row1 = $row1 - 1 $cellpos_row = Floor($row1 / 3) ; If $row= 0, 1, 2 then this=0, if $row= 3,4,5 then this=1, if $row= 6,7,8 then this=2 $cellpos_col = Floor(($column1 - 1) / 3) ; If $column= 1,2,3 then this=0, etc.. For $q = 3 * $cellpos_row To 3 * $cellpos_row + 3 ; (0 to 2) or (3 to 5) or (6 to 8) For $j = 3 * $cellpos_col + 1 To 3 * $cellpos_col + 3 ; (1 to 3) or (4 to 6) or (7 to 9) If $q <> $row1 Or $j <> $column1 Then _possible($q, $j) EndIf Next Next EndIfEndFunc ;==>_possiblecellFunc _allpossible() For $i = 1 To 9 ;checks all possibles For $y = 1 To 9 _possible($i, $y) Next NextEndFunc ;==>_allpossibleFunc _testpossible() While 1 $change = 0 For $i = 1 To 9 For $y = 1 To 9 If _singlepossible($i, $y) = 1 Then $change = 1 _possiblerow($i) _possiblecolumn($y) _possiblecell($i, $y) _nakedpaircolumn($y) _nakedpairrow($i) _nakedpaircell ($i, $y) EndIf Next Next For $i = 1 To 9 $rowtest = _singletoncolumn($i) If $rowtest <> 0 And $rowtest <> "" Then $change = 1 _possiblecolumn($i) _possiblerow($rowtest) _possiblecell($rowtest, $i) _nakedpairrow($rowtest) _nakedpaircolumn($i) _nakedpaircell ($rowtest, $i) EndIf Next For $i = 1 To 9 $columntest = _singletonrow($i) If $columntest <> 0 And $columntest <> "" Then $change = 1 _possiblerow($i) _possiblecolumn($columntest) _possiblecell($i, $columntest) _nakedpairrow($i) _nakedpaircolumn($columntest) _nakedpaircell ($i, $columntest) EndIf Next If $change = 0 Then ExitLoop WEnd EndFunc ;==>_testpossibleFunc _solver2() For $i = 1 To 9 _nakedpaircolumn($i) _nakedpairrow($i) Next For $i = 1 To 9 For $y = 1 to 9 _nakedpaircell ($i, $y) Next Next _testpossible()EndFunc ;==>_solver2Func _nakedpaircolumn($column) Dim $count ;[number] Dim $row[3] Dim $match For $l = 1 To 9 ;row $count = 0 For $d = 1 To 9 ;number If $possibilities[$l][$column][$d] = 1 Then $count = $count + 1 Next If $count = 2 Then $row[1] = $l For $m = $row[1] + 1 To 9 ;row $match = 0 For $p = 1 To 9 ;number If $possibilities[$m][$column][$p] <> $possibilities[$row[1]][$column][$p] Then $match = $match + 1 Next If $match = 0 Then $row[2] = $m ExitLoop (2) EndIf Next EndIf Next If $row[1] <> "" And $row[2] <> "" Then For $d = 1 To 9 ;numbers removed from others If $possibilities[$row[1]][$column][$d] = 1 Then For $l = 1 To 9 ;row If $l <> $row[1] And $l <> $row[2] Then $possibilities[$l][$column][$d] = 0 Next EndIf Next Return 1 EndIfEndFunc ;==>_nakedpaircolumnFunc _nakedpairrow($row) Dim $count ;[number] Dim $column[3] Dim $match For $l = 1 To 9 ;column $count = 0 For $d = 1 To 9 ;number If $possibilities[$row][$l][$d] = 1 Then $count = $count + 1 Next If $count = 2 Then $column[1] = $l For $m = $column[1] + 1 To 9 ;column $match = 0 For $p = 1 To 9 ;number If $possibilities[$row][$m][$p] <> $possibilities[$row][$column[1]][$p] Then $match = $match + 1 Next If $match = 0 Then $column[2] = $m ExitLoop (2) EndIf Next EndIf Next If $column[1] <> "" And $column[2] <> "" Then For $d = 1 To 9 ;numbers removed from others If $possibilities[$row][$column[1]][$d] = 1 Then For $l = 1 To 9 ;column If $l <> $column[1] And $l <> $column[2] Then $possibilities[$row][$l][$d] = 0 Next EndIf Next Return 1 EndIfEndFunc ;==>_nakedpairrowFunc _nakedpaircell($row, $column) Dim $count ;[number] Dim $column[3] Dim $row[3] Dim $match $cellpos_row = Floor($row / 3) ; If $row= 0, 1, 2 then this=0, if $row= 3,4,5 then this=1, if $row= 6,7,8 then this=2 $cellpos_col = Floor(($column - 1) / 3) ; If $column= 1,2,3 then this=0, etc.. For $z = 3 * $cellpos_row To 3 * $cellpos_row + 2 ; (0 to 2) or (3 to 5) or (6 to 8) row For $x = 3 * $cellpos_col + 1 To 3 * $cellpos_col + 3 ; (1 to 3) or (4 to 6) or (7 to 9) column For $d = 1 To 9 ;number If $possibilities[$z][$x][$d] = 1 Then $count = $count + 1 Next If $count = 2 Then $column[1] = $x $row[1] = $z $cellpos_row1 = Floor($row / 3) ; If $row= 0, 1, 2 then this=0, if $row= 3,4,5 then this=1, if $row= 6,7,8 then this=2 $cellpos_col1 = Floor(($column - 1) / 3) ; If $column= 1,2,3 then this=0, etc.. For $u = 3 * $cellpos_row1 To 3 * $cellpos_row1 + 2 ; (0 to 2) or (3 to 5) or (6 to 8) row For $r = 3 * $cellpos_col1 + 1 To 3 * $cellpos_col1 + 3 ; (1 to 3) or (4 to 6) or (7 to 9) column $match = 0 For $p = 1 To 9 ;number If $possibilities[$u][$r][$p] <> $possibilities[$row[1]][$column[1]][$p] Then $match = $match + 1 Next If $match = 0 Then $column[2] = $r $row[2] = $u ExitLoop (2) EndIf Next Next EndIf Next Next If $column[1] <> "" And $column[2] <> "" Then For $d = 1 To 9 ;numbers removed from others If $possibilities[$row[1]][$column[1]][$d] = 1 Then $cellpos_row = Floor($row / 3) ; If $row= 0, 1, 2 then this=0, if $row= 3,4,5 then this=1, if $row= 6,7,8 then this=2 $cellpos_col = Floor(($column - 1) / 3) ; If $column= 1,2,3 then this=0, etc.. For $z = 3 * $cellpos_row To 3 * $cellpos_row + 2 ; (0 to 2) or (3 to 5) or (6 to 8) row For $x = 3 * $cellpos_col + 1 To 3 * $cellpos_col + 3 ; (1 to 3) or (4 to 6) or (7 to 9) column For $d = 1 To 9 ;number If $x <> $column[1] And $x <> $column[2] And $z <> $row[1] And $z <> $row[2] Then $possibilities[$z][$x][$d] = 0 Next Next Next EndIf Next Return 1 EndIfEndFunc ;==>_nakedpaircell;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Func _clear() For $i = 1 To 9 ;row For $j = 1 To 9 ;column $constant[$i][$j] = "" GUICtrlSetData($input[$i - 1][$j], "") Next NextEndFunc ;==>_clearFunc _exit() ExitEndFunc ;==>_exit Edited August 25, 2007 by sccrstvn93 Link to comment Share on other sites More sharing options...
martin Posted August 23, 2007 Share Posted August 23, 2007 (edited) This solver can solve any sudoku as long as it is possible. Input the numbers and then click solve. It uses 2 simple solving methods and then a brute force method. Comments and suggestions are welcome. CODE #include <GUIConstants.au3> #include <array.au3> Global $constant[10][10] ;user numbers [row-1][column] Global $input[10][10] ;input boxes [row-1][column] Global $1 Global $2 Global $3 Global $r Global $c HotKeySet("{esc}", "_exit") $Form1_1 = GUICreate("solver", 633, 374, 189, 173) $Button1 = GUICtrlCreateButton("Solve", 264, 336, 75, 25, 0) For $i = 0 To 8 For $j = 1 To 9 $input[$i][$j] = GUICtrlCreateInput("", 56 * $j, 32 * ($i + 1), 41, 21) Next Next GUISetState(@SW_SHOW) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;_sigletoncolumn cell check problem While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $Button1 _record() _test () EndSwitch WEnd Func _test () Dim $change While 1 While 1 $change = 0 For $q = 1 to 9 For $z = 1 to 9 If $constant[$q-1][$z] = "" Then If _solver1 ($q, $z) = 1 Then $change = 1 EndIf Next Next If $change = 0 Then ExitLoop WEnd For $q = 1 to 9 If _Singletonrow ($q) = 1 then $change = 1 Next For $q = 1 to 9 If _Singletoncolumn($q) = 1 Then $change = 1 Next If $change = 0 Then ExitLoop Wend _brutetest () EndFunc Func _record() For $i = 0 To 9 For $j = 1 To 9 $constant[$i][$j] = GUICtrlRead($input[$i][$j]) Next Next EndFunc ;==>_record Func _rowcheck($row, $column) For $i = 1 To 9 If $i <> $column Then If StringCompare(GUICtrlRead($input[$row - 1][$column]), GUICtrlRead($input[$row - 1][$i])) = 0 Then Return 1 EndIf Next EndFunc ;==>_rowcheck Func _columncheck($row, $column) For $i = 1 To 9 If $i <> $row Then If StringCompare(GUICtrlRead($input[$row - 1][$column]), GUICtrlRead($input[$i - 1][$column])) = 0 Then Return 1 EndIf Next EndFunc ;==>_columncheck Func _brutetest() For $r = 1 To 9 ;row For $c = 1 To 9 ;column If $constant[$r - 1][$c] = "" Then For $n = 1 To 9 ;number to test GUICtrlSetData($input[$r - 1][$c], $n) $1 = _rowcheck($r, $c) $2 = _columncheck($r, $c) $3 = _cellcheck($r, $c) If $1 = 0 And $2 = 0 And $3 = 0 Then ExitLoop Next ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Back track If $1 = 1 Or $2 = 1 Or $3 = 1 Then While 1 GUICtrlSetData($input[$r - 1][$c], $constant[$r - 1][$c]) $c = $c - 1 If $c < 1 Then $c = 9 $r = $r - 1 EndIf If $constant[$r - 1][$c] <> "" Then Else While 1 $back = GUICtrlRead($input[$r - 1][$c]) If $back = "" Then $back = 0 $back = $back + 1 If $back = 10 Then ExitLoop EndIf GUICtrlSetData($input[$r - 1][$c], $back) $1 = _rowcheck($r, $c) $2 = _columncheck($r, $c) $3 = _cellcheck($r, $c) If $1 = 0 And $2 = 0 And $3 = 0 Then ExitLoop (2) WEnd EndIf WEnd EndIf ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EndIf Next Next EndFunc ;==>_brutetest Func _cellcheck($row, $column) $row = $row - 1 $cellpos_row = Floor($row/ 3) ; If $row= 0, 1, 2 then this=0, if $row= 3,4,5 then this=1, if $row= 6,7,8 then this=2 $cellpos_col = Floor(($column - 1) / 3) ; If $column= 1,2,3 then this=0, etc.. For $i = 3 * $cellpos_row To 3 * $cellpos_row + 2 ; (0 to 2) or (3 to 5) or (6 to 8) For $j = 3 * $cellpos_col + 1 To 3 * $cellpos_col + 3 ; (1 to 3) or (4 to 6) or (7 to 9) If $i <> $row Or $j <> $column Then If StringCompare(GUICtrlRead($input[$row][$column]), GUICtrlRead($input[$i][$j])) = 0 Then Return 1 EndIf Next Next EndFunc ;==>_cellcheck Func _randomcheck () While 1 For $t = 0 to 8 For $l = 1 to 9 If $constant[$t][$l] = "" then GUICtrlSetData ($input[$t][$l], Random (1, 9, 1)) EndIf Next Next For $q = 1 to 9 For $z = 1 to 9 If _rowcheck($q, $z) = 1 or _columncheck ($q, $z) = 1 or _cellcheck ($q, $z) = 1 Then ExitLoop (2) Next Next If _rowcheck($q, $z) = 0 and _columncheck ($q, $z) = 0 and _cellcheck ($q, $z) = 0 Then ExitLoop (1) WEnd EndFunc Func _solver1 ($row, $column) ;fills in all single choices Dim $count = 0 Dim $solution For $l = 1 to 9 ;number GUICtrlSetData ($input[$row-1][$column], $l) If _rowcheck ($row, $column) = 0 and _columncheck ($row, $column) = 0 and _cellcheck ($row, $column) = 0 Then $count = $count + 1 $solution = $l EndIf Next GUICtrlSetData ($input[$row-1][$column], "") If $count = 1 Then GUICtrlSetData ($input[$row-1][$column], $solution) $constant[$row-1][$column] = $solution Return 1 EndIf EndFunc Func _Singletoncolumn ($column) ;checks for singletone in given column Dim $solution[10] Dim $solutionrow[10] For $t = 1 to 9 ;row For $l = 1 to 9 ;number If $constant[$t - 1][$column] = "" Then GUICtrlSetData ($input[$t-1][$column], $l) If _rowcheck ($t, $column) = 0 and _columncheck ($t, $column) = 0 and _cellcheck ($t, $column) = 0 Then ;cell check not eliminating numbers $solution[$l] = $solution[$l] + 1 ; freq $solutionrow[$l] = $t EndIf GUICtrlSetData ($input[$t-1][$column], "") EndIf Next Next For $t = 1 to 9 ;checks frenquency If $solution[$t] = 1 Then GUICtrlSetData ($input[$solutionrow[$t] -1][$column], $t) $constant[$solutionrow[$t] -1][$column] = $t Return 1 EndIf Next EndFunc Func _Singletonrow ($row) ;checks for singletone in given row Dim $solution[10] Dim $solutioncolumn[10] For $t = 1 to 9 ;column For $l = 1 to 9 ;number If $constant[$row - 1][$t] = "" Then GUICtrlSetData ($input[$row-1][$t], $l) If _rowcheck ($row, $t) = 0 and _columncheck ($row, $t) = 0 and _cellcheck ($row, $t) = 0 Then $solution[$l] = $solution[$l] + 1 $solutioncolumn[$l] = $t EndIf GUICtrlSetData ($input[$row-1][$t], "") EndIf Next Next For $t = 1 to 9 ;checks frenquency If $solution[$t] = 1 Then GUICtrlSetData ($input[$row - 1][$solutioncolumn[$t]], $t) $constant[$row - 1][$solutioncolumn[$t]] = $t Return 1 EndIf Next EndFunc Func _exit() Exit EndFunc ;==>_exit I haven't looked at how you do it , but I'm impressed how quickly it found a solution to the one attempt I've made so far. It would be interesting to see what Shevilie makes of it wouldn't it? Well done, I didn't feel too confident you would succeed when you started but I'm glad to see I was wrong. Edited August 23, 2007 by martin Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. Link to comment Share on other sites More sharing options...
qazwsx Posted August 23, 2007 Author Share Posted August 23, 2007 Thx, im currently making a faster version that uses possibilities rather than jsut checking every number because possibilities allow for more complex algorithms before the brute test. Link to comment Share on other sites More sharing options...
GEOSoft Posted August 24, 2007 Share Posted August 24, 2007 Looks and works good. Thanks a bunch 1 little comment (suggestion). Change Case $GUI_EVENT_CLOSE to Case -3 and remove the #include <GuiConstants.au3> Unless I missed something (it happens) that seems to be the only place where you used a constant from The GUIConstants file so you have #included a lot of extra constants (and lines) in your script when they are not needed. George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!" Link to comment Share on other sites More sharing options...
qazwsx Posted August 24, 2007 Author Share Posted August 24, 2007 Thx geosoft the does work. Now Version 2: has pair logic Link to comment Share on other sites More sharing options...
qazwsx Posted August 24, 2007 Author Share Posted August 24, 2007 fixed the bug with brute test Link to comment Share on other sites More sharing options...
Achilles Posted August 24, 2007 Share Posted August 24, 2007 I like this!!! I tried it on the hardest one in my big "Sudoku" book and it worked after about 40 seconds. I have a few suggestions:Have a clear button to clear all input boxesHave it disable the inputs so that the user can't interfere with your programMake the GUI a little more user friendly, for example, add some sort of line to let it be easily seen where the 3x3 boxes start/endI looked at your code and noticed you don't use and indentation (at least that's how I got it...). See if this helps you see the logic of your loops more clearly:expandcollapse popupGlobal $constant[10][10];user numbers [row-1][column] Global $input[10][10];input boxes [row-1][column] Global $1 Global $2 Global $3 Global $r Global $c Global $possibilities[10][10][10];[row][column][number] 1 = applicable 0 or "" = not Global $change;change in tests HotKeySet("{esc}", "_exit") StringCompare('Hello', 'Hella') $Form1_1 = GUICreate("solver", 633, 374, 189, 173) $Button1 = GUICtrlCreateButton("Solve", 264, 336, 75, 25, 0) For $i = 0 To 8 For $j = 1 To 9 $input[$i][$j] = GUICtrlCreateInput("", 56 * $j, 32 * ($i + 1), 41, 21) Next Next GUISetState(@SW_SHOW) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;_sigletoncolumn cell check problem While 1 Switch GUIGetMsg() Case - 3 Exit Case $Button1 _record() _allpossible () _testpossible () _solver2 () _brutetest () MsgBox(0, "Solved", "Puzzle Solved") EndSwitch WEnd Func _record() For $i = 1 To 9 For $j = 1 To 9 $constant[$i][$j] = GUICtrlRead($input[$i - 1][$j]) Next Next EndFunc;==>_record Func _rowcheck($row, $column) For $i = 1 To 9 If $i <> $column Then If StringCompare(GUICtrlRead($input[$row - 1][$column]), GUICtrlRead($input[$row - 1][$i])) = 0 Then Return 1 EndIf Next EndFunc;==>_rowcheck Func _columncheck($row, $column) For $i = 1 To 9 If $i <> $row Then If StringCompare(GUICtrlRead($input[$row - 1][$column]), GUICtrlRead($input[$i - 1][$column])) = 0 Then Return 1 EndIf Next EndFunc;==>_columncheck Func _brutetest() For $r = 1 To 9;row For $c = 1 To 9;column If $constant[$r][$c] = "" Then For $n = 1 To 9;number to test GUICtrlSetData($input[$r - 1][$c], $n) $1 = _rowcheck($r, $c) $2 = _columncheck($r, $c) $3 = _cellcheck($r, $c) If $1 = 0 And $2 = 0 And $3 = 0 Then ExitLoop Next If $1 = 1 Or $2 = 1 Or $3 = 1 Then While 1 GUICtrlSetData($input[$r - 1][$c], $constant[$r][$c]) $c = $c - 1 If $c < 1 Then $c = 9 $r = $r - 1 EndIf If $constant[$r][$c] <> "" Then Else While 1 $back = GUICtrlRead($input[$r - 1][$c]) If $back = "" Then $back = 0 $back = $back + 1 If $back = 10 Then ExitLoop EndIf GUICtrlSetData($input[$r - 1][$c], $back) $1 = _rowcheck($r, $c) $2 = _columncheck($r, $c) $3 = _cellcheck($r, $c) If $1 = 0 And $2 = 0 And $3 = 0 Then ExitLoop (2) WEnd EndIf WEnd EndIf EndIf Next Next EndFunc;==>_brutetest Func _cellcheck($row, $column) $row = $row - 1 $cellpos_row = Floor($row / 3); If $row= 0, 1, 2 then this=0, if $row= 3,4,5 then this=1, if $row= 6,7,8 then this=2 $cellpos_col = Floor(($column - 1) / 3); If $column= 1,2,3 then this=0, etc.. For $i = 3 * $cellpos_row To 3 * $cellpos_row + 2; (0 to 2) or (3 to 5) or (6 to 8) For $j = 3 * $cellpos_col + 1 To 3 * $cellpos_col + 3; (1 to 3) or (4 to 6) or (7 to 9) If $i <> $row Or $j <> $column Then If StringCompare(GUICtrlRead($input[$row][$column]), GUICtrlRead($input[$i][$j])) = 0 Then Return 1 EndIf Next Next EndFunc;==>_cellcheck Func _randomcheck() While 1 For $t = 0 To 8 For $l = 1 To 9 If $constant[$t][$l] = "" Then GUICtrlSetData($input[$t][$l], Random(1, 9, 1)) EndIf Next Next For $q = 1 To 9 For $z = 1 To 9 If _rowcheck($q, $z) = 1 Or _columncheck($q, $z) = 1 Or _cellcheck($q, $z) = 1 Then ExitLoop (2) Next Next If _rowcheck($q, $z) = 0 And _columncheck($q, $z) = 0 And _cellcheck($q, $z) = 0 Then ExitLoop (1) WEnd EndFunc;==>_randomcheck ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; using possibilites array Func _possible($row, $column);finds possible entries for a given box For $k = 1 To 9;numbers If $constant[$row][$column] = "" Then GUICtrlSetData($input[$row - 1][$column], $k) If _rowcheck($row, $column) = 0 And _columncheck($row, $column) = 0 And _cellcheck($row, $column) = 0 Then $possibilities[$row][$column][$k] = 1 Else $possibilities[$row][$column][$k] = 0 EndIf GUICtrlSetData($input[$row - 1][$column], "") EndIf Next EndFunc;==>_possible Func _singlepossible($row, $column) Dim $count Dim $answer $count = 0 If $constant[$row][$column] = "" Then For $d = 1 To 9 If $possibilities[$row][$column][$d] = 1 Then $count = $count + 1 $answer = $d EndIf Next If $count = 1 Then GUICtrlSetData($input[$row - 1][$column], $answer) $constant[$row][$column] = $answer Return 1 EndIf EndIf EndFunc;==>_singlepossible Func _singletoncolumn($column) Dim $count Dim $answer Dim $row For $d = 1 To 9;number $count = 0 For $a = 1 To 9;row If $constant[$a][$column] = "" Then If $possibilities[$a][$column][$d] = 1 Then $count = $count + 1 $row = $a EndIf EndIf Next If $count = 1 Then $answer = $d GUICtrlSetData($input[$row - 1][$column], $answer) $constant[$row][$column] = $answer Return $row ExitLoop EndIf Next EndFunc;==>_singletoncolumn Func _singletonrow($row) Dim $count Dim $answer Dim $column For $d = 1 To 9;number $count = 0 For $a = 1 To 9;column If $constant[$row][$a] = "" Then If $possibilities[$row][$a][$d] = 1 Then $count = $count + 1 $column = $a EndIf EndIf Next If $count = 1 Then $answer = $d GUICtrlSetData($input[$row - 1][$column], $answer) $constant[$row][$column] = $answer Return $column ExitLoop EndIf Next EndFunc;==>_singletonrow Func _possiblerow($row1);updates possibilites for row For $p = 1 To 9;column If $constant[$row1][$p] = "" Then _possible($row1, $p) EndIf Next EndFunc;==>_possiblerow Func _possiblecolumn($column1); updates possibilities for column For $p = 1 To 9;row If $constant[$p][$column1] = "" Then _possible($p, $column1) EndIf Next EndFunc;==>_possiblecolumn Func _possiblecell($row1, $column1);updates all possibilities for a cell containging the given box If $constant[$row1][$column1] = "" Then $row1 = $row1 - 1 $cellpos_row = Floor($row1 / 3); If $row= 0, 1, 2 then this=0, if $row= 3,4,5 then this=1, if $row= 6,7,8 then this=2 $cellpos_col = Floor(($column1 - 1) / 3); If $column= 1,2,3 then this=0, etc.. For $q = 3 * $cellpos_row To 3 * $cellpos_row + 3; (0 to 2) or (3 to 5) or (6 to 8) For $j = 3 * $cellpos_col + 1 To 3 * $cellpos_col + 3; (1 to 3) or (4 to 6) or (7 to 9) If $q <> $row1 Or $j <> $column1 Then _possible($q, $j) EndIf Next Next EndIf EndFunc;==>_possiblecell Func _allpossible () For $i = 1 To 9;checks all possibles For $y = 1 To 9 _possible($i, $y) Next Next EndFunc Func _testpossible() While 1 $change = 0 For $i = 1 To 9 For $y = 1 To 9 If _singlepossible($i, $y) = 1 Then $change = 1 _possiblerow($i) _possiblecolumn($y) _possiblecell($i, $y) EndIf Next Next For $i = 1 To 9 $rowtest = _singletoncolumn($i) If $rowtest <> 0 And $rowtest <> "" Then $change = 1 _possiblecolumn($i) _possiblerow($rowtest) _possiblecell($rowtest, $i) EndIf Next For $i = 1 To 9 $columntest = _singletonrow($i) If $columntest <> 0 And $columntest <> "" Then $change = 1 _possiblerow($i) _possiblecolumn($columntest) _possiblecell($i, $columntest) EndIf Next If $change = 0 Then ExitLoop WEnd EndFunc;==>_testpossible Func _solver2() While 1 For $i = 1 To 9 _paircolumn($i) _pairrow($i) Next _testpossible () If $change = 0 then ExitLoop WEnd EndFunc;==>_solver2 Func _paircolumn($column) Dim $count;[number] Dim $row[3] Dim $match For $l = 1 To 9;row $count = 0 For $d = 1 To 9;number If $possibilities[$l][$column][$d] = 1 Then $count = $count + 1 Next If $count = 2 Then $row[1] = $l For $m = $row[1] + 1 To 9;row $match = 0 For $p = 1 To 9;number If $possibilities[$m][$column][$p] <> $possibilities[$row[1]][$column][$p] Then $match = $match + 1 Next If $match = 0 Then $row[2] = $m ExitLoop (2) EndIf Next EndIf Next If $row[1] <> "" And $row[2] <> "" Then For $d = 1 To 9;numbers removed from others If $possibilities[$row[1]][$column][$d] = 1 Then For $l = 1 To 9;row If $l <> $row[1] And $l <> $row[2] Then $possibilities[$l][$column][$d] = 0 Next EndIf Next Return 1 EndIf EndFunc;==>_paircolumn Func _pairrow($row) Dim $count;[number] Dim $column[3] Dim $match For $l = 1 To 9;column $count = 0 For $d = 1 To 9;number If $possibilities[$row][$l][$d] = 1 Then $count = $count + 1 Next If $count = 2 Then $column[1] = $l For $m = $column[1] + 1 To 9;column $match = 0 For $p = 1 To 9;number If $possibilities[$row][$m][$p] <> $possibilities[$row][$column[1]][$p] Then $match = $match + 1 Next If $match = 0 Then $column[2] = $m ExitLoop (2) EndIf Next EndIf Next If $column[1] <> "" And $column[2] <> "" Then For $d = 1 To 9;numbers removed from others If $possibilities[$row][$column[1]][$d] = 1 Then For $l = 1 To 9;column If $l <> $column[1] And $l <> $column[2] Then $possibilities[$row][$l][$d] = 0 Next EndIf Next Return 1 EndIf EndFunc;==>_pairrow Func _exit() Exit EndFunc;==>_exitLast of all, anybody know how to tell Scite to update? I had to download the new version of autoit for this but Scite still isn't recognizing "StringCompare", however when I click "Start -> Programs -> AutoIt -> RunScript" it works fine... My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list] Link to comment Share on other sites More sharing options...
Achilles Posted August 24, 2007 Share Posted August 24, 2007 (edited) This is what I meant by changing the GUI, feel free to change this to whatever... I also made the font bigger and set the text to center. I know there is something to make it so that the input can only receive numbers but I can't find it (in my very brief search). expandcollapse popup#include <GuiConstants.au3> Dim $input[9][10] $Form1_1 = GUICreate("solver", 610, 374, 189, 173) $Button1 = GUICtrlCreateButton("Solve", 260, 338, 75, 25, 0) $XaddAmmount = 0 $YaddAmmount = 0 GuiSetFont(11) For $i = 0 To 8 If $i = 3 or $i = 6 or $i = 9 then $YaddAmmount += 15 EndIf For $j = 1 To 9 $x = 56 * $j - 60 $y = 32 * ($i + 1) - 10 If Mod($j - 1, 3) = 0 then $XaddAmmount += 30 EndIf $input[$i][$j] = GUICtrlCreateInput("", $x + $XaddAmmount, $y + $YaddAmmount, 36, 23, $ES_CENTER) Next $XaddAmmount = 0 Next GUISetState(@SW_SHOW) While 1 Switch GuiGetMsg() Case -3 Exit EndSwitch WEnd Edited August 24, 2007 by Piano_Man My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list] Link to comment Share on other sites More sharing options...
qazwsx Posted August 25, 2007 Author Share Posted August 25, 2007 Thx for the gui ill add that. My script is indented in scite the indents must have been lost when i copied it. When you dl the latest version of autoit which one do you pick from the dl page? Link to comment Share on other sites More sharing options...
Achilles Posted August 25, 2007 Share Posted August 25, 2007 (edited) Thx for the gui ill add that. My script is indented in scite the indents must have been lost when i copied it.Your welcome... and I thought that might be the problem because that has happened to me sometimes. When you dl the latest version of autoit which one do you pick from the dl page?From here I picked the first one in the list for the AutoIt3 (not beta), then for beta I picked the third one. However I think the problem is more with scite, because the helpfile shows the StringCompare() and when I doubleclick on the .au3 icon it works fine but when I open scite and try to run it doesn't work (because it can't find the function StringCompare)...EDIT: This works now, and I don't know what I did to fix it... Anyways thanks for the help! Edited August 25, 2007 by Piano_Man My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list] Link to comment Share on other sites More sharing options...
qazwsx Posted August 25, 2007 Author Share Posted August 25, 2007 updated gui and clear button. Link to comment Share on other sites More sharing options...
AngelSL Posted August 25, 2007 Share Posted August 25, 2007 I like hitting Solve when theres no numbers - it practically generates a puzzle and solves it. Link to comment Share on other sites More sharing options...
martin Posted August 25, 2007 Share Posted August 25, 2007 updated gui and clear button.Looks better now and seems fast.Maybe you could check that the numbers entered are legal. If you put the same number more than once in a row or column it shouldn't try to solve it. Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. Link to comment Share on other sites More sharing options...
qazwsx Posted August 25, 2007 Author Share Posted August 25, 2007 Maybe you could check that the numbers entered are legal. If you put the same number more than once in a row or column it shouldn't try to solve it.I don't quite understand what your saying. Are you talking about the brute test? Link to comment Share on other sites More sharing options...
qazwsx Posted August 25, 2007 Author Share Posted August 25, 2007 Now has naked pairs for cells as well Link to comment Share on other sites More sharing options...
GEOSoft Posted August 25, 2007 Share Posted August 25, 2007 Thx geosoft the does work.Now Version 2: has pair logicYW but I see you still have it #included and I hate that file with a vengence.When you use it you are actually #including 17 files with a total of 643 constants. No matter I just run it through my constants replacer script.The latest version works well though. George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!" Link to comment Share on other sites More sharing options...
martin Posted August 25, 2007 Share Posted August 25, 2007 I don't quite understand what your saying. Are you talking about the brute test?I mean someone can enter numbers which are illegal. I tried putting two 4s in one column, and two 4s in one row. Your script then will try forever to solve it. Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. Link to comment Share on other sites More sharing options...
qazwsx Posted August 25, 2007 Author Share Posted August 25, 2007 ohh you mean check the user inputs for the original puzzle? Yeh i can add that. Im currently working on locked candidates but im having some problems. Link to comment Share on other sites More sharing options...
qazwsx Posted August 27, 2007 Author Share Posted August 27, 2007 (edited) I have added a couple of new solving strategies but i ahve not been able to get them to work so i think im done with the solver. If anyone would want to continue working on it i can give you the newest code. The new code contains naked triples and locked candidates but neither of them work. Edited August 27, 2007 by sccrstvn93 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now