Sudoku refactor (#3556)
* BacktrackingAlgorithm refactor * DancingLinks refactor
This commit is contained in:
parent
bd9a87c137
commit
43a4d08c36
|
@ -3,25 +3,25 @@ package com.baeldung.algorithms.sudoku;
|
|||
import java.util.stream.IntStream;
|
||||
|
||||
public class BacktrackingAlgorithm {
|
||||
|
||||
private static int BOARD_SIZE = 9;
|
||||
private static int SUBSECTION_SIZE = 3;
|
||||
private static int BOARD_START_INDEX = 0;
|
||||
|
||||
private static int NO_VALUE = 0;
|
||||
private static int MIN_VALUE = 1;
|
||||
private static int MAX_VALUE = 9;
|
||||
|
||||
public static int[][] board = {
|
||||
{ 8, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 3, 6, 0, 0, 0, 0, 0 },
|
||||
{ 0, 7, 0, 0, 9, 0, 2, 0, 0 },
|
||||
{ 0, 5, 0, 0, 0, 7, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 4, 5, 7, 0, 0 },
|
||||
{ 0, 0, 0, 1, 0, 0, 0, 3, 0 },
|
||||
{ 0, 0, 1, 0, 0, 0, 0, 6, 8 },
|
||||
{ 0, 0, 8, 5, 0, 0, 0, 1, 0 },
|
||||
{ 0, 9, 0, 0, 0, 0, 4, 0, 0 }
|
||||
private static final int BOARD_SIZE = 9;
|
||||
private static final int SUBSECTION_SIZE = 3;
|
||||
private static final int BOARD_START_INDEX = 0;
|
||||
|
||||
private static final int NO_VALUE = 0;
|
||||
private static final int MIN_VALUE = 1;
|
||||
private static final int MAX_VALUE = 9;
|
||||
|
||||
private static int[][] board = {
|
||||
{8, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 3, 6, 0, 0, 0, 0, 0},
|
||||
{0, 7, 0, 0, 9, 0, 2, 0, 0},
|
||||
{0, 5, 0, 0, 0, 7, 0, 0, 0},
|
||||
{0, 0, 0, 0, 4, 5, 7, 0, 0},
|
||||
{0, 0, 0, 1, 0, 0, 0, 3, 0},
|
||||
{0, 0, 1, 0, 0, 0, 0, 6, 8},
|
||||
{0, 0, 8, 5, 0, 0, 0, 1, 0},
|
||||
{0, 9, 0, 0, 0, 0, 4, 0, 0}
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
@ -30,7 +30,7 @@ public class BacktrackingAlgorithm {
|
|||
solver.printBoard();
|
||||
}
|
||||
|
||||
public void printBoard() {
|
||||
private void printBoard() {
|
||||
for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) {
|
||||
for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) {
|
||||
System.out.print(board[row][column] + " ");
|
||||
|
@ -39,7 +39,7 @@ public class BacktrackingAlgorithm {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean solve(int[][] board) {
|
||||
private boolean solve(int[][] board) {
|
||||
for (int r = BOARD_START_INDEX; r < BOARD_SIZE; r++) {
|
||||
for (int c = BOARD_START_INDEX; c < BOARD_SIZE; c++) {
|
||||
if (board[r][c] == NO_VALUE) {
|
||||
|
@ -47,9 +47,8 @@ public class BacktrackingAlgorithm {
|
|||
board[r][c] = k;
|
||||
if (isValid(board, r, c) && solve(board)) {
|
||||
return true;
|
||||
} else {
|
||||
board[r][c] = NO_VALUE;
|
||||
}
|
||||
board[r][c] = NO_VALUE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -58,16 +57,22 @@ public class BacktrackingAlgorithm {
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean isValid(int[][] board, int r, int c) {
|
||||
return (rowConstraint(board, r) &&
|
||||
columnConstraint(board, c) &&
|
||||
subsectionConstraint(board, r, c));
|
||||
private boolean isValid(int[][] board, int r, int c) {
|
||||
return rowConstraint(board, r) &&
|
||||
columnConstraint(board, c) &&
|
||||
subsectionConstraint(board, r, c);
|
||||
}
|
||||
|
||||
private boolean subsectionConstraint(int[][] board, int r, int c) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
for (int i = (r / SUBSECTION_SIZE) * SUBSECTION_SIZE; i < (r / SUBSECTION_SIZE) * SUBSECTION_SIZE + SUBSECTION_SIZE; i++) {
|
||||
for (int j = (c / SUBSECTION_SIZE) * SUBSECTION_SIZE; j < (c / SUBSECTION_SIZE) * SUBSECTION_SIZE + SUBSECTION_SIZE; j++) {
|
||||
int subsectionRowStart = (r / SUBSECTION_SIZE) * SUBSECTION_SIZE;
|
||||
int subsectionRowEnd = subsectionRowStart + SUBSECTION_SIZE;
|
||||
|
||||
int subsectionColumnStart = (c / SUBSECTION_SIZE) * SUBSECTION_SIZE;
|
||||
int subsectionColumnEnd = subsectionColumnStart + SUBSECTION_SIZE;
|
||||
|
||||
for (int i = subsectionRowStart; i < subsectionRowEnd; i++) {
|
||||
for (int j = subsectionColumnStart; j < subsectionColumnEnd; j++) {
|
||||
if (!checkConstraint(board, i, constraint, j)) return false;
|
||||
}
|
||||
}
|
||||
|
@ -76,23 +81,19 @@ public class BacktrackingAlgorithm {
|
|||
|
||||
private boolean columnConstraint(int[][] board, int c) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
for (int i = BOARD_START_INDEX; i < BOARD_SIZE; i++) {
|
||||
if (!checkConstraint(board, i, constraint, c)) return false;
|
||||
}
|
||||
return true;
|
||||
return IntStream.range(BOARD_START_INDEX, BOARD_SIZE)
|
||||
.allMatch(i -> checkConstraint(board, i, constraint, c));
|
||||
}
|
||||
|
||||
private boolean rowConstraint(int[][] board, int r) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
for (int i = BOARD_START_INDEX; i < BOARD_SIZE; i++) {
|
||||
if (!checkConstraint(board, r, constraint, i)) return false;
|
||||
}
|
||||
return true;
|
||||
return IntStream.range(BOARD_START_INDEX, BOARD_SIZE)
|
||||
.allMatch(i -> checkConstraint(board, r, constraint, i));
|
||||
}
|
||||
|
||||
private boolean checkConstraint(int[][] board, int r, boolean[] constraint, int c) {
|
||||
if (board[r][c] >= MIN_VALUE && board[r][c] <= MAX_VALUE) {
|
||||
if (constraint[board[r][c] - 1] == false) {
|
||||
if (board[r][c] != NO_VALUE) {
|
||||
if (!constraint[board[r][c] - 1]) {
|
||||
constraint[board[r][c] - 1] = true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -100,4 +101,4 @@ public class BacktrackingAlgorithm {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ class ColumnNode extends DancingNode {
|
|||
int size;
|
||||
String name;
|
||||
|
||||
public ColumnNode(String n) {
|
||||
ColumnNode(String n) {
|
||||
super();
|
||||
size = 0;
|
||||
name = n;
|
||||
|
|
|
@ -50,10 +50,9 @@ public class DancingLinks {
|
|||
|
||||
private ColumnNode makeDLXBoard(boolean[][] grid) {
|
||||
final int COLS = grid[0].length;
|
||||
final int ROWS = grid.length;
|
||||
|
||||
ColumnNode headerNode = new ColumnNode("header");
|
||||
ArrayList<ColumnNode> columnNodes = new ArrayList<ColumnNode>();
|
||||
List<ColumnNode> columnNodes = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < COLS; i++) {
|
||||
ColumnNode n = new ColumnNode(Integer.toString(i));
|
||||
|
@ -62,10 +61,10 @@ public class DancingLinks {
|
|||
}
|
||||
headerNode = headerNode.R.C;
|
||||
|
||||
for (int i = 0; i < ROWS; i++) {
|
||||
for (boolean[] aGrid : grid) {
|
||||
DancingNode prev = null;
|
||||
for (int j = 0; j < COLS; j++) {
|
||||
if (grid[i][j] == true) {
|
||||
if (aGrid[j]) {
|
||||
ColumnNode col = columnNodes.get(j);
|
||||
DancingNode newNode = new DancingNode(col);
|
||||
if (prev == null)
|
||||
|
@ -82,21 +81,21 @@ public class DancingLinks {
|
|||
return headerNode;
|
||||
}
|
||||
|
||||
public DancingLinks(boolean[][] cover) {
|
||||
DancingLinks(boolean[][] cover) {
|
||||
header = makeDLXBoard(cover);
|
||||
}
|
||||
|
||||
public void runSolver() {
|
||||
answer = new LinkedList<DancingNode>();
|
||||
answer = new LinkedList<>();
|
||||
search(0);
|
||||
}
|
||||
|
||||
public void handleSolution(List<DancingNode> answer) {
|
||||
private void handleSolution(List<DancingNode> answer) {
|
||||
int[][] result = parseBoard(answer);
|
||||
printSolution(result);
|
||||
}
|
||||
|
||||
int size = 9;
|
||||
private int size = 9;
|
||||
|
||||
private int[][] parseBoard(List<DancingNode> answer) {
|
||||
int[][] result = new int[size][size];
|
||||
|
@ -120,12 +119,12 @@ public class DancingLinks {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static void printSolution(int[][] result) {
|
||||
private static void printSolution(int[][] result) {
|
||||
int N = result.length;
|
||||
for (int i = 0; i < N; i++) {
|
||||
String ret = "";
|
||||
for (int[] aResult : result) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
for (int j = 0; j < N; j++) {
|
||||
ret += result[i][j] + " ";
|
||||
ret.append(aResult[j]).append(" ");
|
||||
}
|
||||
System.out.println(ret);
|
||||
}
|
||||
|
|
|
@ -1,39 +1,37 @@
|
|||
package com.baeldung.algorithms.sudoku;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class DancingLinksAlgorithm {
|
||||
private static int BOARD_SIZE = 9;
|
||||
private static int SUBSECTION_SIZE = 3;
|
||||
private static int NO_VALUE = 0;
|
||||
private static int CONSTRAINTS = 4;
|
||||
private static int MIN_VALUE = 1;
|
||||
private static int MAX_VALUE = 9;
|
||||
private static int COVER_START_INDEX = 1;
|
||||
private static final int BOARD_SIZE = 9;
|
||||
private static final int SUBSECTION_SIZE = 3;
|
||||
private static final int NO_VALUE = 0;
|
||||
private static final int CONSTRAINTS = 4;
|
||||
private static final int MIN_VALUE = 1;
|
||||
private static final int MAX_VALUE = 9;
|
||||
private static final int COVER_START_INDEX = 1;
|
||||
|
||||
public static int[][] board = {
|
||||
{ 8, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 3, 6, 0, 0, 0, 0, 0 },
|
||||
{ 0, 7, 0, 0, 9, 0, 2, 0, 0 },
|
||||
{ 0, 5, 0, 0, 0, 7, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 4, 5, 7, 0, 0 },
|
||||
{ 0, 0, 0, 1, 0, 0, 0, 3, 0 },
|
||||
{ 0, 0, 1, 0, 0, 0, 0, 6, 8 },
|
||||
{ 0, 0, 8, 5, 0, 0, 0, 1, 0 },
|
||||
{ 0, 9, 0, 0, 0, 0, 4, 0, 0 }
|
||||
};
|
||||
private static int[][] board = {
|
||||
{8, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 3, 6, 0, 0, 0, 0, 0},
|
||||
{0, 7, 0, 0, 9, 0, 2, 0, 0},
|
||||
{0, 5, 0, 0, 0, 7, 0, 0, 0},
|
||||
{0, 0, 0, 0, 4, 5, 7, 0, 0},
|
||||
{0, 0, 0, 1, 0, 0, 0, 3, 0},
|
||||
{0, 0, 1, 0, 0, 0, 0, 6, 8},
|
||||
{0, 0, 8, 5, 0, 0, 0, 1, 0},
|
||||
{0, 9, 0, 0, 0, 0, 4, 0, 0}
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
DancingLinksAlgorithm solver = new DancingLinksAlgorithm();
|
||||
solver.solve(board);
|
||||
}
|
||||
|
||||
public boolean solve(int[][] board) {
|
||||
private void solve(int[][] board) {
|
||||
boolean[][] cover = initializeExactCoverBoard(board);
|
||||
DancingLinks dlx = new DancingLinks(cover);
|
||||
dlx.runSolver();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getIndex(int row, int col, int num) {
|
||||
|
@ -54,7 +52,7 @@ public class DancingLinksAlgorithm {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Row constrain.
|
||||
for (int r = COVER_START_INDEX; r <= BOARD_SIZE; r++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
|
||||
|
@ -74,7 +72,7 @@ public class DancingLinksAlgorithm {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Subsection constraint
|
||||
for (int br = COVER_START_INDEX; br <= BOARD_SIZE; br += SUBSECTION_SIZE) {
|
||||
for (int bc = COVER_START_INDEX; bc <= BOARD_SIZE; bc += SUBSECTION_SIZE) {
|
||||
|
|
|
@ -39,11 +39,11 @@ class DancingNode {
|
|||
this.U.D = this.D.U = this;
|
||||
}
|
||||
|
||||
public DancingNode() {
|
||||
DancingNode() {
|
||||
L = R = U = D = this;
|
||||
}
|
||||
|
||||
public DancingNode(ColumnNode c) {
|
||||
DancingNode(ColumnNode c) {
|
||||
this();
|
||||
C = c;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue