2015-11-02 70 views
1

所以我試圖用遞歸和回溯來解決4x4數獨。 當我打電話SolveSmallSudoku(L); 「現在解決...」 它給了我這個「錯誤,(在SolveSmallSudoku中)矩陣索引超出範圍」 但我無法發現任何與我的矩陣L有關的索引。這似乎是我的程序沒有正確執行我的回溯部分。我認爲我的findPossibleEntries過程正常工作。它確實找到了該特定單元格的所有可能值。任何人有任何提示?解決楓4X4數獨

> 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,然後我建議你移除'',你就可以自己看到它。請注意以下常見行爲,當結束此循環時,會得到5作爲'y'的最終值:'對於y,從1到4做;結束了:y;'。 – acer

+0

感謝您的澄清。你知道這個「通常行爲」背後的想法,for循環中的條件是「y <= 4」而不是「y <4」嗎? (請注意,我不是OP,爲什麼我沒有對發佈的代碼進行任何嚴格的調試。) – harre