2011-10-24 65 views
1

這是我第一次將遞歸作爲一個低級別課程中的任務。我環顧了互聯網,我似乎無法找到任何人使用類似於我提出的方法(可能會說爲什麼這不起作用)。該錯誤是std::__copy_move...中的一個段錯誤,我假設它是C++ STL中的一個東西。 Anywho,我的代碼如下:遞歸回溯數獨求解問題,C++

bool sudoku::valid(int x, int y, int value) 
{ 
    if (x < 0) {cerr << "No valid values exist./n";} 

    if (binary_search(row(x).begin(), row(x).end(), value)) 
     {return false;}     //if found in row x, exit, otherwise: 
    else if (binary_search(col(y).begin(), col(y).end(), value)) 
     {return false;}     //if found in col y, exit, otherwise: 
    else if (binary_search(box((x/3), (y/3)).begin(), box((x/3), (y/3)).end(), value)) 
     {return false;}     //if found in box x,y, exit, otherwise: 
    else 
     {return true;}     //the value is valid at this index 
} 

int sudoku::setval(int x, int y, int val) 
{ 
    if (y < 0 && x > 0) {x--; y = 9;} //if y gets decremented past 0 go to previous row. 
    if (y > 8) {y %= 9; x++;}   //if y get incremented past 8 go to next row. 

    if (x == 9) {return 0;}    //base case, puzzle done. 
    else { 
     if (valid(x,y,val)){   //if the input is valid 
      matrix[x][y] = val;   //set the element equal to val 
      setval(x,y++,val);   //go to next element 
     } 
     else { 
      setval(x,y,val++);   //otherwise increment val 
      if(val > 9) {val = value(x,y--); setval(x,y--,val++); } 
     }        //if val gets above 9, set val to prev element, 
    }         //and increment the last element until valid and start over 
} 

我一直在試圖總結我的頭圍繞這件事了一會兒,我似乎無法找出什麼地方出了錯。任何建議都非常感謝! :)

+0

什麼是矩陣?在不知道這些細節的情況下,很難爲您調試代碼。 – Flexo

+1

我認爲你應該重溫算法設計。在遞歸的'if'部分,你在遞歸之前檢查了有效性,在'else'部分中,你沒有進行有效性檢查。另外,你只能在遞歸之後檢查'val> 9'。 – arne

+0

首先寫入setval做什麼。特別是想: if(!valid(x,y,val))setval嘗試在其他(x,y)paire中重複指定val,但如果它對任何(x,y)無效怎麼辦? – lkanab

回答

0

下面所有的是Unix而不是Windows。

std::__copy_move...是STL好的。但是STL本身並不做任何事情,你的代碼中的一些函數調用會以錯誤的參數或錯誤的狀態調用它。你需要弄清楚。

如果您有來自seg-fault的核心轉儲,那麼只需執行pstack <core file name>,您將看到崩潰的完整調用堆棧。然後看看代碼中涉及哪部分,並從那裏開始調試(添加痕跡/ couts/...)。

通常你會得到這個核心文件具有很好的可讀名稱,但如果你不這樣做,你可以使用nmc++filt等來dismangle的名稱。

最後,pstack只是一個小CMD行實用程序,您可以隨時二進制(生成該核心)和核心文件加載到像gdbSun Studio或調試器調試器內置到IDE和沿看到同樣的事情有很多其他信息和選項。

HTH

1

sudoku::setval應該返回int但也有它返回什麼都沒有的至少兩條路徑。你應該弄清楚在其他路徑中需要返回什麼,否則你會得到隨機未定義的行爲。

1

沒有更多的信息,這是不可能告訴。例如,所涉及的數據爲 結構,以及返回什麼rowcol。 不過,也有一些明顯的問題:

  • sudoku::valid,你檢查什麼似乎是一個錯誤 條件(x < 0),但你不回;你仍然繼續你的 測試,使用負值x

  • 而且在sudoku:valid:做rowcol真正迴歸 排序值參考?如果這些值沒有排序,那麼binary_search將 有未定義的行爲(如果它們是,這些名稱是有點誤導的 )。如果它們返回值(副本),而不是對同一個對象的引用,那麼begin()end(), 函數會參考不同對象—再次,未定義 的行爲。

  • 最後,我沒有在你的算法中看到任何回溯,我也沒有看到它是如何進展到一個解決方案的。

FWIW:當我寫類似的東西,我使用的用於板81個 元件的簡單陣列,然後創建了映射 索引(0 – 80)到適當的行,列和箱靜態數組。對於每個 這九個行,列和框,我保留了一組使用的值(一個 位圖);這使得檢查合法性非常微不足道,這意味着我可以通過遞增 索引來增加到下一個方塊來測試。由此產生的代碼非常簡單。

獨立使用,你需要的數據表示的:一些 「全局」(可能是一個的sudoku成員)意味着知道是否你已經 找到了解決辦法還是不行;一個循環某處嘗試九個方塊中的每一個的可能值(當解決方案發現時,停止 )以及遞歸。如果你沒有使用簡單的數組作爲 板,就像我一樣,我會爲索引建議一個類或一個結構,使用 函數,該函數會一勞永逸地處理增量。

0

如果多次遞歸地輸入一個函數,可能會(並且會發生)分段錯誤。 我注意到導致它的一個場景。但我很確定還有更多。

提示:在你的話寫任何功能的目的 - 如果它過於複雜寫 - 功能也許應該被拆分...

0

好像你的算法是有點「野蠻forcy」。約束滿足問題(CSP)通常不是一個好策略。我寫了一個數獨解算器,而回(希望我仍然有源代碼,這是在我發現github上),並且我能找到的最快的算法模擬退火:

http://en.wikipedia.org/wiki/Simulated_annealing

這是概率性的,但它對於IIRC這個問題,通常比其他方法快幾個數量級。

HTH!