解数独中的裸三元组
我希望我在大学时能更加关注数学课。 :)
我如何实现这个裸三元组的数学公式?
裸三元组
取三个共享单位 U 的单元格 C = {c1, c2, c3}。取三个数字 N = {n1, n2, n3}。如果 C 中的每个单元格都有 ci ⊆ N 作为其候选单元格,那么我们可以删除所有单元格 ni ∈ N 来自 U 中的其他单元格。**
我有一个方法,它采用一个单位(例如一个盒子、一行或一列)作为参数。 该单元包含 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];
}
}
}
非常感谢您的帮助,
I wished I paid more attention to the math classes back in Uni. :)
How do I implement this math formula for naked triples?
Naked Triples
Take three cells C = {c1, c2, c3} that share a unit U. Take three numbers
N = {n1, n2, n3}. If each cell in C has as its candidates ci ⊆ N then we can remove all
ni ∈ N from the other cells in U.**
I have a method that takes a Unit (e.g. a Box, a row or a column) as parameter.
The unit contains 9 cells, therefore I need to compare all combinations of 3 cells at a time that from the box, perhaps put them into a stack or collection for further calculation.
Next step would be taking these 3-cell-combinations one by one and compare their candidates against 3 numbers. Again these 3 numbers can be any possible combination from 1 to 9. Thats all I need.
But how would I do that? How many combinations would I get? Do I get 3 x 9 = 27 combinations for cells and then the same for numbers (N)?
How would you solve this in classic C# loops? No Lambda expression please I am already confused enough :)
Code:
I had to cut the classes short in order to represent them here.
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;
}
}
}
}
Candidate
public class Candidate : INotifyPropertyChanged
{
private int? _value;
public int? Value { ... }
}
Box:
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];
}
}
}
Board
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];
}
}
}
Many Thanks for any help,
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
伪代码算法;我的C有点生锈了。
我建议从候选值中找到所有可能的三数组合。可以有 6 到 504 个这样的组合,具体取决于您有多少候选者(由 n!/(3!*(n-3)!) 给出)。
对于每一个,循环遍历单元中的所有单元格,看看它们是否符合条件,即它们没有任何不在您的组合中的数字。如果某个组合有三个或以上,那么就可以应用它。
希望这有帮助!如果您需要的话,我将 C-ify 这段代码;无论如何,我一直想温习我的C。
另外,如果您还不知道,有一种更简单的方法可以使用计算机解决数独难题,而不涉及任何逻辑的手动编程。但我认为你尝试这样做的方式是相当高尚的。
生成所有可能的组合的数组
有很多方法可以做到这一点,并且可能有一个最好的方法;我自己还没有对此进行过认真的研究。我推荐谷歌:组合算法...我实际上发现C 中的一个解决方案 我自己。
请务必附上支票,以确保您的候选人数量合适。对于 n=3,只有一种可能的候选组合,您的算法应该为您找到它。对于 n=1 和 n=2,裸三元组甚至不适用。
Psuedo-Code algorithm; my C is a bit rusty.
I recommend finding all of the possible three-number combinations from your candidate values. There can be anywhere from 6 to 504 such combinations, depending on how many candidates you have (given by n!/(3!*(n-3)!) ).
For each one, cycle through all of the cells in the unit and see if they match the condition that they don't have any numbers not in your combination. If a certain combination has three or more, then you can apply it.
Hope this helps! I'll C-ify this code if you need it; I've been meaning to brush up on my C anyways.
Also, in case you didn't already know, there's a much simpler way to solve Sudoku puzzles using computers that doesn't involve manually programming in any logic. But I think the way you're trying to do it is quite noble.
Generating an array of all possible combos
There are many ways to do this, and there might be a best one; I haven't done any serious research on it myself. I'd recommend google: combination algorithm... I actually found one solution in C myself.
Be sure to include a check to make sure that your number of candidates is appropriate. For n=3, there is only one possible candidate combination, and your algorithm should find it for you. For n=1 and n=2, Naked Triples doesn't even apply.