• Авторизация


Возвращаясь к судоку 04-10-2007 13:18 к комментариям - к полной версии - понравилось!


Как я отмечал ранее, формализация методов решения судоку (в отличие от решения самих головоломок) представляет из себя вполне достойную задачу для головы. Мне удалось реализовать 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 методов.
Возможно, допишу, когда очередное вспышка мыслительной активности в голове произойдёт.
вверх^ к полной версии понравилось! в evernote
Комментарии (3):
BELLO_INCIERTO 04-10-2007-13:23 удалить
;) Ну, и куда нам, дурам набитым, теперь деваться? ;)
MintOla 04-10-2007-13:31 удалить
Дело в том, что в сложных судоку есть свои особенности. Рано или поздно при их разгадывании наступает момент, когда нужно числа подбирать (или угадывать, кому как нравится). Просто применяется банальный метод подбора. Вы, конечно, молодец, что всё это произвели ( я имею ввиду прогу, написанную Вами), но... Намного интереснее самому голову "поломать" в расставлении чисел, чем просто их вбить в программку и всё. Хотя, я думаю, у вас была цель именно создания этой программы ради её создания, нежели ради разгадывания судоку. Желаю удачи!
Mike_Solo 04-10-2007-14:29 удалить
BELLO_INCIERTO, вот не надо прибедняться, всё равно не поверю! :-D
MintOla, конечно же, самостоятельное создание программы было самоцелью! В интернете их и так куча :-)
А что касается угадывания, то это такой же формальный метод - просчитывание хода вперед, только писать его сложнее.


Комментарии (3): вверх^

Вы сейчас не можете прокомментировать это сообщение.

Дневник Возвращаясь к судоку | Mike_Solo - Sans espoir et sans regret | Лента друзей Mike_Solo / Полная версия Добавить в друзья Страницы: раньше»