Как я отмечал
ранее, формализация методов решения судоку (в отличие от решения самих головоломок) представляет из себя вполне достойную задачу для головы. Мне удалось реализовать 3 очевидных метода в нехитром Perl-скрипте.
print ("SUDOKU solver\nVersion 1.0 draft by Mike Solo\n");
print ("Initializing variables\n");
$Cell="123456789";
$vid="";
@map = (["9","0","0","0","0","6","0","0","0"],
["0","7","0","0","2","0","0","0","0"],
["4","0","1","0","0","7","6","0","0"],
["0","0","0","0","0","0","1","5","0"],
["0","9","0","3","5","1","0","0","0"],
["0","0","4","0","8","0","0","0","0"],
["0","8","9","0","1","0","3","4","0"],
["5","0","2","0","0","3","0","6","0"],
["0","0","3","9","6","0","0","0","0"]);
print ("Data initialized.\n");
print ("Enter SUDOKU data by rows, 0 for empty cells \(9 digits for the row\).\n");
for ($i=0; $i<9; $i++) {
do { print ("\nEnter sudoku string number",$i+1,"->");
$instr=
;
chomp($instr);}
while ( $instr !~m/\d{9}/ || length($instr) != 9 );
for ($j=0; $j<9; $j++) {
$estr=substr($instr,$j,1);
if ($estr == 0) {$map[$i][$j]=$Cell;} else {$map[$i][$j]=$estr;}
# Replacement operator
if ($map[$i][$j] == 0) {$map[$i][$j]=$Cell;}
}
}
# -------------------------------------- PROCESSING --------------------------
do {
do {
do { # ----- Stage ONE clean-up SINGLES
#sweep rows and columns
$mcount=0;
for ($i=0; $i<9; $i++) { for ($j=0; $j<9; $j++) {
if (length($map[$i][$j]) == 1) {
$xn=$map[$i][$j];
for ($k=0; $k<9; $k++) {
if ($k != $j) { if ($map[$i][$k] =~s/$xn/$vid/) {$mcount++;} }
}
for ($k=0; $k<9; $k++) {
if ($k != $i) { if ($map[$k][$j] =~s/$xn/$vid/) {$mcount++;} }
}
}}} # closing two FORs anf IF
#sweep areas
for ($ai=0; $ai<3; $ai++) { for ($aj=0; $aj<3; $aj++) {
for ($i=0; $i<3; $i++) { for ($j=0; $j<3; $j++) {
$rdx=3*$ai+$i;
$cdx=3*$aj+$j;
if (length($map[$rdx][$cdx]) == 1) {
$xn=$map[$rdx][$cdx];
for ($k=0; $k<3; $k++) {for ($l=0; $l<3; $l++) {
if ($k != $i || $l != $j) { if ($map[3*$ai+$k][3*$aj+$l] =~s/$xn/$vid/) {$mcount++;} }
}}
}
}}}}
# print ("\nSingles eliminated:",$mcount);
} while ($mcount != 0);
# --------- Stage TWO - clean-up DUALS
#search for DUALS - AREA mode
$mcount=0;
for ($ai=0; $ai<3; $ai++) { for ($aj=0; $aj<3; $aj++) { for ($i=0; $i<3; $i++) { for ($j=0; $j<3; $j++) {
$rdx=3*$ai+$i;
$cdx=3*$aj+$j;
if (length($map[$rdx][$cdx]) == 2) {
$dual = $map[$rdx][$cdx];
$duax = substr($dual,0,1);
$duay = substr($dual,1,1);
# look for another dual in a row:
for ($k=0; $k<9; $k++)
{
if ($map[$rdx][$k] == $dual && $k !=$cdx)
{
for ($l=0; $l<9; $l++)
{
if($l != $k && $l != $cdx)
{
if ($map[$rdx][$l] =~s/$duax/$vid/) {$mcount++;}
if ($map[$rdx][$l] =~s/$duay/$vid/) {$mcount++;}
}
}
}
}
# look for another dual in a column:
for ($k=0; $k<9; $k++)
{
if ($map[$k][$cdx] == $dual && $k !=$rdx)
{
for ($l=0; $l<9; $l++)
{
if($l != $k && $l != $rdx)
{
if ($map[$l][$cdx] =~s/$duax/$vid/) {$mcount++;}
if ($map[$l][$cdx] =~s/$duay/$vid/) {$mcount++;}
}
}
}
}
# look for another dual in the area: (horror)
for ($k=0; $k<3; $k++) {for ($l=0; $l<3; $l++) {
if ( ($i != $k || $j != $l) && $map[3*$ai+$k][3*$aj+$l] == $dual) # second match lookup
{
for ($m=0; $m<3; $m++) {
for ($n=0; $n<3; $n++) # sweep area
{
if (!(($m == $i && $n == $j) || ($m == $k && $n == $l)))
{
if ($map[3*$ai+$m][3*$aj+$n] =~s/$duax/$vid/) {$mcount++;}
if ($map[3*$ai+$m][3*$aj+$n] =~s/$duay/$vid/) {$mcount++;}
}
}}
}
}}
} # closing dual finding IF
}}}} # closing 4 FORs
# print ("\nDuals processed:",$mcount);
} while ($mcount !=0);
# ------- Stage 3 - fing 'the only possible'
$mcount = 0;
for ($z=1; $z<10; $z++) # let Z be that 'only possible'
{
for ($ai=0; $ai<3; $ai++) { for ($aj=0; $aj<3; $aj++) { for ($i=0; $i<3; $i++) { for ($j=0; $j<3; $j++) {
$rdx=3*$ai+$i;
$cdx=3*$aj+$j;
if ($map[$rdx][$cdx] =~m/$z/ && length($map[$rdx][$cdx]) > 1 ) {
# print("\n",$z,"found at:",$rdx,$cdx);
# check for another match in a row:
$xcount=0;
for ($k=0; $k<9; $k++)
{
if ($map[$rdx][$k] =~m/$z/ && $k !=$cdx)
{
$xcount++;
}
}
if ( $xcount == 0) {
$map[$rdx][$cdx] = $z;
# print("a");
$mcount++;
}
# look for single in a column:
$xcount=0;
for ($k=0; $k<9; $k++)
{
if ($map[$k][$cdx] =~m/$z/ && $k !=$rdx)
{
$xcount++;
}
}
if ( $xcount == 0) {
$map[$rdx][$cdx] = $z;
# print("b");
$mcount++;
}
# look for single in the area:
$xcount=0;
for ($k=0; $k<3; $k++) {for ($l=0; $l<3; $l++) {
if ( $map[3*$ai+$k][3*$aj+$l] =~m/$z/ && ($i != $k || $j != $l)) # another match lookup
{
$xcount++;
}
}}
if ( $xcount == 0) {
$map[$rdx][$cdx] = $z;
# print("c");
$mcount++;
}
} # closing sole candidate finding IF
}}}} # closing 4 FORs
} # clozing Z FOR
# print ("\nSole canditates defined:",$mcount);
} while ($mcount !=0);
for ($i=0; $i<9; $i++) { for ($j=0; $j<9; $j++) { $mcount = $mcount + $map[$i][$j]; }}
if ($mcount == 405) { print ("\n\nSUDOKU solved!");} else { print ("\n\nNo more ideas. SUDOKU not solved.");}
print ("\nResult table:");
for ($i=0; $i<9; $i++) {
print ("\n\n");
for ($j=0; $j<9; $j++) {
printf("%-10.10s",$map[$i][$j]);
}
}
Он успешно решает судоку начального уровня и немного усложнённые. А вот сложные не может, маловато 3 методов.
Возможно, допишу, когда очередное вспышка мыслительной активности в голове произойдёт.