Sign in to follow this  
Followers 0
qazwsx

Sudoku Solver Updated V2.1

19 posts in this topic

#1 ·  Posted (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 well

Now has a updated Gui and a clear button Thx to Piano_man for the gui

CODE

#include <GuiConstants.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

Global $possibilities[10][10][10] ;[row][column][number] 1 = applicable 0 or "" = not

Global $change ;change in tests

HotKeySet("{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 = 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)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;_sigletoncolumn cell check problem

While 1

$nMsg = GUIGetMsg()

Switch $nMsg

Case - 3

Exit

Case $Button1

_record()

_allpossible()

_testpossible()

_solver2()

MsgBox(0, "Solved", "Puzzle Solved")

Case $Button2

_clear()

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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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

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 ;==>_allpossible

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)

_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 ;==>_testpossible

Func _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 ;==>_solver2

Func _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

EndIf

EndFunc ;==>_nakedpaircolumn

Func _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

EndIf

EndFunc ;==>_nakedpairrow

Func _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

EndIf

EndFunc ;==>_nakedpaircell

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Func _clear()

For $i = 1 To 9 ;row

For $j = 1 To 9 ;column

$constant[$i][$j] = ""

GUICtrlSetData($input[$i - 1][$j], "")

Next

Next

EndFunc ;==>_clear

Func _exit()

Exit

EndFunc ;==>_exit

Edited by sccrstvn93

Share this post


Link to post
Share on other sites

#2 ·  Posted (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 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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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!"

Share this post


Link to post
Share on other sites

Thx geosoft the does work.

Now Version 2: has pair logic

Share this post


Link to post
Share on other sites

fixed the bug with brute test

Share this post


Link to post
Share on other sites

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 boxes
  • Have it disable the inputs so that the user can't interfere with your program
  • Make 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/end
I 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:

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
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;==>_exit

Last 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]

Share this post


Link to post
Share on other sites

#8 ·  Posted (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).

#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 by Piano_Man

My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list]

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
Share on other sites

#10 ·  Posted (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 by Piano_Man

My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list]

Share this post


Link to post
Share on other sites

updated gui and clear button.

Share this post


Link to post
Share on other sites

I like hitting Solve when theres no numbers - it practically generates a puzzle and solves it.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
Share on other sites

Now has naked pairs for cells as well

Share this post


Link to post
Share on other sites

Thx geosoft the does work.

Now Version 2: has pair logic

YW 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!"

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

#19 ·  Posted (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 by sccrstvn93

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0