2015-11-02 71 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