Sudoku refactor (#3556)

* BacktrackingAlgorithm refactor

* DancingLinks refactor
This commit is contained in:
Grzegorz Piwowarek 2018-01-31 18:50:37 +01:00 committed by GitHub
parent bd9a87c137
commit 43a4d08c36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 78 deletions

View File

@ -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;
}
}
}

View File

@ -4,7 +4,7 @@ class ColumnNode extends DancingNode {
int size;
String name;
public ColumnNode(String n) {
ColumnNode(String n) {
super();
size = 0;
name = n;

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;
}