2015-11-02 4 views
1

Так что я пытаюсь использовать рекурсию и обратную трассировку для решения судоку 4x4. Когда я вызываю SolveSmallSudoku (L); «Решить сейчас ...» это дает мне эту ошибку «Ошибка, (в SolveSmallSudoku)», не указана « Но я не могу обнаружить ошибку, связанную с индексами моей матрицы L. Похоже, что моя программа не выполняет мою функцию возврата. Я думаю, что моя процедура findPossibleEntries работает нормально. Он находит все возможные значения для этой определенной ячейки. Кто-нибудь получил намек?Решение 4X4 sudoku in maple

> L := Matrix(4,4,[ [0,4,0,0],[2,0,0,3],[4,0,0,1],[0,0,3,0] ]); 
> isFull := proc(L) 
    local x, y;  
     for x from 1 to 4 do 
     for y from 1 to 4 do 
     if L[x,y]=0 then 
       return false; 
       end if; 
      end do; 
     end do; 

     return true; 
     end proc; 

>findPossibleEntries := proc(L, i, j) 
    local x, y, possible:=[0,0,0,0]; 
    local r:=1, c:=1; 


#Checking possible entries in ith row 
for y from 1 to 4 do 
    if not L[i,y] = 0 then 
     possible[L[i,y]] := 1;  
    end if; 
end do; 

#Checking possible entries in jth col 
for x from 1 to 4 do 
    if not L[x,j] = 0 then 
     possible[L[x,j]] := 1; 

    end if; 
end do; 

#Checking possible entries block by block 
if i >= 1 and i <= 2 then 
    r := 1; 
elif i >= 3 and i <= 4 then 
    r := 3; 
end if; 

if j >= 1 and j <= 2 then 
    c := 1; 
elif j >= 3 and j <= 4 then 
    c := 3; 
end if; 

#Using for-loop to find possible entries in the block 
for x in range(r, r+1) do 
     for y in range(c, c+1) do 

      if not L[x,y] = 0 then 
       possible[L[x,y]] := 1; 
      end if; 
     end do; 
end do; 


#Now the list, possible, only holds the possible entries 
for x from 1 to 4 do 
    if possible[x] = 0 then 
     possible[x] := x; 
    else 
     possible[x] := 0; 
    end if; 
end do; 

return possible; 

end proc; 

>SolveSmallSudoku := proc(L) 
local x, y, i:=0, j:=0, possibleVal:=[0,0,0,0]; 

if isFull(L) then 
    print("Solved!"); 
    print(L); 
    return; 
else 
    print("Solving now..."); 

    for x from 1 to 4 do 
     for y from 1 to 4 do 
      if L[x,y] = 0 then 
       i:=x; 
       j:=y; 
       break; 
      end if 
     end do; 
     #Breaks the outer loop as well 
     if L[x,y] = 0 then 
      break; 
     end if 

    end do;  

#Finds all the possibilities for i,j 
possibleVal := findPossibleEntries(L,i,j); 

#Traverses the list, possibleVal to find the correct entries and finishes the sudoku recursively 
for x from 1 to 4 do 
    if not possibleVal[x] = 0 then 
     L[i,j]:= possibleVal[x]; 
     SolveSmallSudoku(L); 
    end if; 
end do; 
#Backtracking 
L[i,j]:= 0; 

end if; 


end proc; 

ответ

1

Избавиться,

#Breaks the outer loop as well 
    if L[x,y] = 0 then 
     break; 
    end if 

Как было это изначально, что внешняя проверка пытается получить доступ к L [1,5] для данного примера L.

Вместо замены break во внутреннем цикле с,

x:=4; break; 

Это приведет к тому, чтобы внешний цикл также завершается при следующей итерация (которая происходит сразу после того, как внутренний цикл заканчивается или прерывается. Таким образом, вы получите полный перерыв, который вам нужен.

Код, похоже, работает так, как вы планировали, и решение печатается для вашего примера ввода.

+0

Не могли бы вы указать, где y установлено в 5? – harre

+0

Вы можете увидеть это самостоятельно, запустив в отладчике или 'print (x, y)' прямо перед внешним ', если L [x, y] = 0 then', который я предложил вам удалить. Обратите внимание на следующее обычное поведение, которое приводит к 5 в качестве окончательного значения для 'y' при завершении этого цикла:' для y от 1 до 4 do; end do: y; '. – acer

+0

Благодарим вас за разъяснения. Знаете ли вы идею этого «обычного поведения», где условие в for-loop является 'y <= 4' вместо' y <4'? (Заметьте, что я не ОП, почему я не предпринял серьезной отладки в отправленном коде.) – harre