Ограничения Двумерного Массива: Судоку
Я пытаюсь решить судоку как задача удовлетворения ограничений для домашнего задания. Я уже построил ограничения для всех элементов в определенной строке, а также для столбцов. Я пытаюсь построить ограничения для элементов в субрегионе, отличных друг от друга, и я сталкиваюсь с некоторыми проблемами.
общая идея моего текущего алгоритма заключается в добавлении всех переменных, которые находятся в субрегионе (например, поле 3x3 для 9x9 grid) в список, а затем переставить все значения в этом списке, чтобы построить NotEqualConstraints между каждой переменной. Приведенный ниже код работает правильно для 1-го субрегиона сетки NxN, но я не уверен, как я должен изменить это, чтобы перебрать остальную часть всей сетки.
int incSize = (int)Math.sqrt(svars.length);
ArrayList<Variable> subBox = new ArrayList<Variable>();
for (int ind = 0; ind < incSize; ind++) {
for (int ind2 = 0; ind2 < incSize; ind2++) {
subBox.add(svars[ind][ind2]);
}
}
for (int i = 0; i < subBox.size(); i++) {
for (int j = i + 1; j < subBox.size(); j++) {
NotEqualConstraint row = new NotEqualConstraint(subBox.get(i), subBox.get(j));
constraints.add(row);
}
}
может ли кто-нибудь направить меня в правильном направлении о том, как я могу изменить код, чтобы поразить каждый субрегион, а не только верхний левый?
edit: я также открыт для любых попыток алгоритм, который работает, не обязательно добавлять все значения в ArrayList для каждого субрегиона. Если вы видите лучший способ, пожалуйста, поделитесь insight
4 ответов
вот рабочее решение, которое я придумал, для тех, кто заинтересован:
for (int ofs = 0; ofs < svars.length; ofs++) {
int col = (ofs % incSize) * incSize;
int row = ((int)(ofs / incSize)) * incSize;
ArrayList<Variable> subBox = new ArrayList<Variable>();
for (int ind = row; ind < row+incSize; ind++) {
for (int ind2 = col; ind2 < col+incSize; ind2++) {
subBox.add(svars[ind][ind2]);
}
}
for (int i = 0; i < subBox.size(); i++) {
for (int j = i + 1; j < subBox.size(); j++) {
NotEqualConstraint c = new NotEqualConstraint(subBox.get(i), subBox.get(j));
constraints.add(c);
}
}
}
Я не совсем уверен, что вы пытаетесь сделать, но ниже алгоритм должен дать вам все необходимое. Вы можете просто игнорировать и / или удалять значения, которые вам не нужны. Вероятно, вы могли бы заполнить все свои массивы соответствующим образом в точке, где у вас есть все номера.
слова, которые я использую:
- square: один квадрат, чтобы поместить число.
- субрегион: группа квадратов, сетка 3x3 в классическом судоку.
- головоломки: все это, 3x3 субрегионов и 9x9 квадратов.
код:
//You should have these values at this point:
int subRegionWidth = something; //amount of horizontal squares in a subregion
int subRegionHeight = something; //amount of vertical squares in a subregion
int amountOfHorizontalSubRegions = something; //amount of subRegion columns next to each other
int amountOfVerticalSubRegions = something; //amount of subregion rows on top of each other
//Doesn't change, so calculated once in advance:
int squaresPerPuzzleRow = subRegionWidth*amountOfHorizontalSubRegions;
//Variables to use inside the loop:
int subRegionIndex = 0;
int squareColumnInPuzzle;
int squareRowInPuzzle;
int squareIndexInPuzzle;
int squareIndexInSubRegion;
for(int subRegionRow=0; subRegionRow<amountOfVerticalSubRegions;subRegionRow++)
{
for(int subRegionColumn=0; subRegionColumn<amountOfHorizontalSubRegions;subRegionColumn++)
{
for(int squareRowInRegion=0; squareRowInRegion<subRegionHeight; squareRowInRegion++)
{
for(int squareColumnInRegion=0; squareColumnInRegion<subRegionWidth; squareColumnInRegion++)
{
squareColumnInPuzzle = subRegionColumn*subRegionWidth + squareColumnInRegion;
squareRowInPuzzle = subRegionRow*subRegionHeight + squareRowInRegion;
squareIndexInPuzzle = squareRowInPuzzle*squaresPerPuzzleRow + squareColumnInPuzzle;
squareIndexInSubRegion = squareRowInRegion*subRegionWidth + squareColumnInRegion;
//You now have all the information of a square:
//The subregion's row (subRegionRow)
//The subregion's column (subRegionColumn)
//The subregion's index (subRegionIndex)
//The square's row within the puzzle (squareRowInPuzzle)
//The square's column within the puzzle (squareColumnInPuzzle)
//The square's index within the puzzle (squareIndexInPuzzle)
//The square's row within the subregion (squareRowInSubRegion)
//The square's column within the subregion (squareColumnInSubRegion)
//The square's index within the subregion (squareIndexInSubRegion)
//You'll get this once for all squares, add the code to do something with it here.
}
}
subRegionIndex++;
}
}
Если вам нужны только верхние левые квадраты на субрегион, просто удалите внутренние две петли:
for(int subRegionRow=0; subRegionRow<amountOfVerticalSubRegions;subRegionRow++)
{
for(int subRegionColumn=0; subRegionColumn<amountOfHorizontalSubRegions;subRegionColumn++)
{
squareColumnInPuzzle = subRegionColumn*subRegionWidth;
squareRowInPuzzle = subRegionRow*subRegionHeight;
squareIndexInPuzzle = squareRowInPuzzle*squaresPerPuzzleRow + squareColumnInPuzzle;
//You now have all the information of a top left square:
//The subregion's row (subRegionRow)
//The subregion's column (subRegionColumn)
//The subregion's index (subRegionIndex)
//The square's row within the puzzle (squareRowInPuzzle)
//The square's column within the puzzle (squareColumnInPuzzle)
//The square's index within the puzzle (squareIndexInPuzzle)
//The square's row within the subregion (always 0)
//The square's column within the subregion (always 0)
//The square's index within the subregion (always 0)
//You'll get this once for all squares, add the code to do something with it here.
subRegionIndex++;
}
}
for (int start1 = start1; start1 < svars.length/incSize; start1 ++) {
for (int start2 = start2; start2 < svars.length/incSize; start2++) {//iterate through all subsets
ArrayList<Variable> subBox = new ArrayList<Variable>();
for (int ind = start1*incSize; ind < incSize; ind++) {
for (int ind2 = start2*incSize; ind2 < incSize; ind2++) {
subBox.add(svars[ind][ind2]);
}
}
for (int i = 0; i < subBox.size(); i++) {
for (int j = i + 1; j < subBox.size(); j++) {
NotEqualConstraint row = new NotEqualConstraint(subBox.get(i), subBox.get(j));
constraints.add(row);
}
}
}
}
Я не совсем понял, что вы пытаетесь сделать, но если вы пытаетесь решить головоломку, вам просто нужен рекурсивный метод, который будет помещать числа, пока он не заполнит всю сетку, и головоломка действительна.Это было мое решение для futoshiki puzzle solver (аналогично судоку)