2010-06-10 37 views
5

我希望我更加關注Uni中的數學課。 :)解決Sudoku中的裸三元組

如何實現這個裸數學公式的數學公式?

裸三同
取三個小區C = {C1,C2,C3}共享一個單元U.採取三個數字 N = {N1,N2,N3}。如果C中的每個單元格都有它的候選項,那麼我們可以從U中的其他單元格中刪除所有的 ni∈N。**

我有一個方法需要一個單元(例如一個框,一行或一列)作爲參數。該單元包含9個細胞,因此我需要從盒子中一次比較3個細胞的所有組合,可能將它們放入堆棧或集合中以供進一步計算。

下一步將逐個採取這些3細胞組合,並比較他們的候選人對3個數字。這3個數字再次可以是從1到9的任何可能組合。這就是我需要的。

但我該怎麼做?我會得到多少種組合?對於單元格,我得到3 x 9 = 27個組合,然後相同的數字(N)?

你會如何解決這個經典的C#循環?沒有Lambda表達請我已經很困惑:)

代碼: 我不得不削減類爲了代表他們在這裏。

public class Cell : INotifyPropertyChanged 
    { 

public ObservableCollection<ObservableCollection<Candidate>> CandidateActual {...} 

public int Id { ... } 

//Position of the Cell inside a box if applicable 
public int CellBoxPositionX { get; private set; } 
public int CellBoxPositionY { get; private set; } 

//Position of the Cell inside the game board 
public int CellBoardPositionX { get; private set; } 
public int CellBoardPositionY { get; private set; } 

//Position of the Box inside the game board 
public int BoxPositionX { get; private set; } 
public int BoxPositionY { get; private set; } 

public int CountCandidates { ... }  
public int? Value { ...} 

public Candidate this[int number] 
     { 
      get 
      { 
       if (number < 1 || number > PossibleValues.Count) 
       { 
        throw new ArgumentOutOfRangeException("number", number, "Invalid Number Index"); 
       } 

       switch (number) 
       { 
        case 1: 
         return CandidateActual[0][0]; 
        case 2: 
         return CandidateActual[0][1]; 
        case 3: 
         return CandidateActual[0][2]; 
        case 4: 
         return CandidateActual[1][0]; 
        case 5: 
         return CandidateActual[1][1]; 
        case 6: 
         return CandidateActual[1][2]; 
        case 7: 
         return CandidateActual[2][0]; 
        case 8: 
         return CandidateActual[2][1]; 
        case 9: 
         return CandidateActual[2][2]; 
        default: 
         return null; 
       } 
      } 
     } 
} 

候選

public class Candidate : INotifyPropertyChanged 
    { 

     private int? _value; 

     public int? Value { ... } 

    } 

盒:

public class Box : INotifyPropertyChanged 
    { 

public ObservableCollection<ObservableCollection<Cell>> BoxActual { ... } 

public Cell this[int row, int column] 
     { 
      get 
      { 
       if(row < 0 || row >= BoxActual.Count) 
       { 
        throw new ArgumentOutOfRangeException("row", row, "Invalid Row Index"); 
       } 
       if(column < 0 || column >= BoxActual.Count) 
       { 
        throw new ArgumentOutOfRangeException("column", column, "Invalid Column Index"); 
       } 
       return BoxActual[row][column]; 
      } 
     } 
} 

public class Board : INotifyPropertyChanged 
    { 

public ObservableCollection<ObservableCollection<Box>> GameBoard {...} 

public Cell this[int boardRowPosition, int boardColumnPosition] 
     { 
      get 
      { 
       int totalSize = GameBoard.Count*GameBoard.Count(); 
       if (boardRowPosition < 0 || boardRowPosition >= totalSize) 
        throw new ArgumentOutOfRangeException("boardRowPosition", boardRowPosition, "Invalid boardRowPosition index"); 
       if (boardColumnPosition < 0 || boardColumnPosition >= totalSize) 
        throw new ArgumentOutOfRangeException("boardColumnPosition", boardColumnPosition, "Invalid boardColumnPosition index"); 
       return 
        GameBoard[boardRowPosition/GameBoard.Count][boardColumnPosition/GameBoard.Count][ 
         boardRowPosition%GameBoard.Count, boardColumnPosition%GameBoard.Count]; 
      } 
     } 



     public Box this[int boardRowPosition, int boardColumnPosition, bool b] 
     { 
      get 
      { 
       int totalSize = GameBoard.Count * GameBoard.Count(); 
       if (boardRowPosition < 0 || boardRowPosition >= totalSize) 
        throw new ArgumentOutOfRangeException("boardRowPosition", boardRowPosition, "Invalid boardRowPosition index"); 
       if (boardColumnPosition < 0 || boardColumnPosition >= totalSize) 
        throw new ArgumentOutOfRangeException("boardColumnPosition", boardColumnPosition, "Invalid boardColumnPosition index"); 
       return 
        GameBoard[boardRowPosition/GameBoard.Count][boardColumnPosition/GameBoard.Count]; 
      } 
     } 
} 

很多感謝您的幫助,

+1

您的問題不完整。我們需要更多地瞭解你現有的代碼(例如Unit和Cell的類定義,以及如何維護候選人等)。否則,這只是一個邏輯謎題,根本不是一個編程問題。 – 2010-06-10 22:16:08

+0

當然喬爾。希望我的代碼片段有所幫助。謝謝 – Houman 2010-06-10 22:43:19

+0

hehe ahhhh好,編程將是一個挑戰; o) – Houman 2010-06-12 12:07:23

回答

1

僞代碼算法;我的C有點生疏。

我建議從候選值中找出所有可能的三數組合。根據你有多少候選人(由n!/(3!*(n-3)!)),可以有6到504個這樣的組合。

對於每個單元,循環遍歷單元中的所有單元格,並查看它們是否符合條件,即它們沒有任何數字不在您的組合中。如果某個組合有三個或更多,那麼您可以應用它。

combos = (array containing 3-long combination of candidates) 
for each combo in combos     # iterate through every combo 
    matches = new array     # initialize a blank array 
    for each cell in unit 
    if (cell does not contain candidates other than the ones in your current combo) 
     matches.add(cell)     # this is a match! 
    end 
    end 

    if matches.size >= 3     # naked triple found! (three matches for given combo) 
    for each cell in unit 
     if (cell is not in matches) 
     (delete every candidate in current combo in this cell) 
     end 
    end 
    end 
    delete matches       # clear up memory 
end 

希望這有助於!如果你需要的話,我會C-ify這個代碼;無論如何,我一直有意識地去研究我的C語言。

另外,如果你還不知道,有一種更簡單的方法來解決Sudoku難題使用計算機,不涉及任何邏輯手動編程。但我認爲你嘗試這樣做的方式非常高尚。


生成所有可能的組合技的數組

有很多方法可以做到這一點,有可能是一個最好的一個;我自己沒有對此進行任何認真的研究。我建議谷歌:combination algorithm ...我自己實際上發現one solution in C

一定要包括一張支票,以確保您的候選人人數是適當的。對於n = 3,只有一個可能的候選組合,並且您的算法應該爲您找到它。對於n = 1和n = 2,Naked Triples甚至不適用。

+0

非常感謝你爲這個優秀的僞代碼。這是有道理的,並幫助我理解。特別是Factorial的使用非常棒。我仍然有問題想出這一步: combos =(包含3長候選人組合的數組) 我還不知道一個有效的方法來做到這一點。你能詳細闡述一下嗎?很多謝謝 – Houman 2010-06-12 13:32:51

+0

關於這個c!/(c-3)!,它是否適用於單位內所有可能的候選人?但在這種情況下,c是什麼?候選人人數最多?我不明白這個...... – Houman 2010-06-12 16:53:00

+0

c!/(c-3)!是給定n個可能候選人的可能候選組合的* count *。所以,有6個可能的候選人,你有6!/ 3! = 120.請注意,計算此效率更有效的方法是n *(n-1)*(n-2),這相當於並且更便宜。 我將編輯我的文章,以包含許多方法之一來生成您的組合數組,因爲它很難在此框中格式化。 – 2010-06-12 18:16:10