2010-06-10 35 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