From 914abdb9a498b75e206f91f53c264e7f4d848283 Mon Sep 17 00:00:00 2001 From: iaforek Date: Sun, 28 Jan 2018 18:14:29 +0000 Subject: [PATCH] Updated code - mostly with CONSTANTS. Extracted methods. --- .../sudoku/BacktrackingAlgorithm.java | 119 ++++++++++-------- .../sudoku/DancingLinksAlgorithm.java | 86 +++++++------ 2 files changed, 114 insertions(+), 91 deletions(-) diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java index effdcd9c04..25c8285e0e 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java @@ -1,18 +1,28 @@ package com.baeldung.algorithms.sudoku; -public class BacktrackingAlgorithm { +import java.util.stream.IntStream; - static char[][] board = { - { '8', '.', '.', '.', '.', '.', '.', '.', '.' }, - { '.', '.', '3', '6', '.', '.', '.', '.', '.' }, - { '.', '7', '.', '.', '9', '.', '2', '.', '.' }, - { '.', '5', '.', '.', '.', '7', '.', '.', '.' }, - { '.', '.', '.', '.', '4', '5', '7', '.', '.' }, - { '.', '.', '.', '1', '.', '.', '.', '3', '.' }, - { '.', '.', '1', '.', '.', '.', '.', '6', '8' }, - { '.', '.', '8', '5', '.', '.', '.', '1', '.' }, - { '.', '9', '.', '.', '.', '.', '4', '.', '.' } - }; +public class BacktrackingAlgorithm { + + private static int BOARD_SIZE = 9; + private static int SUBSECTION_SIZE = 3; + private static int BOARD_INDEX_START = 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 } + }; public static void main(String[] args) { BacktrackingAlgorithm solver = new BacktrackingAlgorithm(); @@ -21,24 +31,24 @@ public class BacktrackingAlgorithm { } public void printBoard() { - for (int i = 0; i < 9; i++) { - for (int j = 0; j < 9; j++) { - System.out.print(board[i][j] + " "); - } + IntStream.range(BOARD_INDEX_START, BOARD_SIZE).forEach(row -> { + IntStream.range(BOARD_INDEX_START, BOARD_SIZE).forEach(column -> { + System.out.print(board[row][column] + " "); + }); System.out.println(); - } + }); } - public boolean solve(char[][] board) { - for (int r = 0; r < board.length; r++) { - for (int c = 0; c < board[0].length; c++) { - if (board[r][c] == '.') { - for (int k = 1; k <= 9; k++) { - board[r][c] = (char) ('0' + k); + public boolean solve(int[][] board) { + for (int r = BOARD_INDEX_START; r < BOARD_SIZE; r++) { + for (int c = BOARD_INDEX_START; c < BOARD_SIZE; c++) { + if (board[r][c] == NO_VALUE) { + for (int k = MIN_VALUE; k <= MAX_VALUE; k++) { + board[r][c] = k; if (isValid(board, r, c) && solve(board)) { return true; } else { - board[r][c] = '.'; + board[r][c] = NO_VALUE; } } return false; @@ -48,39 +58,44 @@ public class BacktrackingAlgorithm { return true; } - public boolean isValid(char[][] board, int r, int c) { - boolean[] row = new boolean[9]; - for (int i = 0; i < 9; i++) { - if (board[r][i] >= '1' && board[r][i] <= '9') { - if (row[board[r][i] - '1'] == false) { - row[board[r][i] - '1'] = true; - } else { - return false; - } + public 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++) { + if (!checkConstraint(board, i, constraint, j)) return false; } } + return true; + } - boolean[] col = new boolean[9]; - for (int i = 0; i < 9; i++) { - if (board[i][c] >= '1' && board[i][c] <= '9') { - if (col[board[i][c] - '1'] == false) { - col[board[i][c] - '1'] = true; - } else { - return false; - } - } + private boolean columnConstraint(int[][] board, int c) { + boolean[] constraint = new boolean[BOARD_SIZE]; + for (int i = BOARD_INDEX_START; i < BOARD_SIZE; i++) { + if (!checkConstraint(board, i, constraint, c)) return false; } + return true; + } - boolean[] grid = new boolean[9]; - for (int i = (r / 3) * 3; i < (r / 3) * 3 + 3; i++) { - for (int j = (c / 3) * 3; j < (c / 3) * 3 + 3; j++) { - if (board[i][j] >= '1' && board[i][j] <= '9') { - if (grid[board[i][j] - '1'] == false) { - grid[board[i][j] - '1'] = true; - } else { - return false; - } - } + private boolean rowConstraint(int[][] board, int r) { + boolean[] constraint = new boolean[BOARD_SIZE]; + for (int i = BOARD_INDEX_START; i < BOARD_SIZE; i++) { + if (!checkConstraint(board, r, constraint, i)) return false; + } + return true; + } + + 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) { + constraint[board[r][c] - 1] = true; + } else { + return false; } } return true; diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java index 5cff88c644..057a15c594 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java @@ -3,28 +3,32 @@ package com.baeldung.algorithms.sudoku; import java.util.*; public class DancingLinksAlgorithm { - private static int S = 9; - private static int SIDE = 3; + 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; - static char[][] board = { - { '8', '.', '.', '.', '.', '.', '.', '.', '.' }, - { '.', '.', '3', '6', '.', '.', '.', '.', '.' }, - { '.', '7', '.', '.', '9', '.', '2', '.', '.' }, - { '.', '5', '.', '.', '.', '7', '.', '.', '.' }, - { '.', '.', '.', '.', '4', '5', '7', '.', '.' }, - { '.', '.', '.', '1', '.', '.', '.', '3', '.' }, - { '.', '.', '1', '.', '.', '.', '.', '6', '8' }, - { '.', '.', '8', '5', '.', '.', '.', '1', '.' }, - { '.', '9', '.', '.', '.', '.', '4', '.', '.' } + 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 } }; public static void main(String[] args) { - DancingLinksAlgorithm solver = new DancingLinksAlgorithm(); solver.solve(board); } - public boolean solve(char[][] board) { + public boolean solve(int[][] board) { boolean[][] cover = initializeExactCoverBoard(board); DancingLinks dlx = new DancingLinks(cover); dlx.runSolver(); @@ -33,46 +37,50 @@ public class DancingLinksAlgorithm { } private int getIndex(int row, int col, int num) { - return (row - 1) * S * S + (col - 1) * S + (num - 1); + return (row - 1) * BOARD_SIZE * BOARD_SIZE + (col - 1) * BOARD_SIZE + (num - 1); } private boolean[][] createExactCoverBoard() { - boolean[][] R = new boolean[9 * 9 * 9][9 * 9 * 4]; + boolean[][] R = new boolean[BOARD_SIZE * BOARD_SIZE * MAX_VALUE][BOARD_SIZE * BOARD_SIZE * CONSTRAINTS]; int hBase = 0; - for (int r = 1; r <= S; r++) { - for (int c = 1; c <= S; c++, hBase++) { - for (int n = 1; n <= S; n++) { + // Cell constraint. + for (int r = COVER_START_INDEX; r <= BOARD_SIZE; r++) { + for (int c = COVER_START_INDEX; c <= BOARD_SIZE; c++, hBase++) { + for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++) { int index = getIndex(r, c, n); R[index][hBase] = true; } } } - - for (int r = 1; r <= S; r++) { - for (int n = 1; n <= S; n++, hBase++) { - for (int c1 = 1; c1 <= S; c1++) { + + // Row constrain. + for (int r = COVER_START_INDEX; r <= BOARD_SIZE; r++) { + for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) { + for (int c1 = COVER_START_INDEX; c1 <= BOARD_SIZE; c1++) { int index = getIndex(r, c1, n); R[index][hBase] = true; } } } - for (int c = 1; c <= S; c++) { - for (int n = 1; n <= S; n++, hBase++) { - for (int r1 = 1; r1 <= S; r1++) { + // Column constraint. + for (int c = COVER_START_INDEX; c <= BOARD_SIZE; c++) { + for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) { + for (int r1 = COVER_START_INDEX; r1 <= BOARD_SIZE; r1++) { int index = getIndex(r1, c, n); R[index][hBase] = true; } } } - - for (int br = 1; br <= S; br += SIDE) { - for (int bc = 1; bc <= S; bc += SIDE) { - for (int n = 1; n <= S; n++, hBase++) { - for (int rDelta = 0; rDelta < SIDE; rDelta++) { - for (int cDelta = 0; cDelta < SIDE; cDelta++) { + + // 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) { + for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) { + for (int rDelta = 0; rDelta < SUBSECTION_SIZE; rDelta++) { + for (int cDelta = 0; cDelta < SUBSECTION_SIZE; cDelta++) { int index = getIndex(br + rDelta, bc + cDelta, n); R[index][hBase] = true; } @@ -83,14 +91,14 @@ public class DancingLinksAlgorithm { return R; } - private boolean[][] initializeExactCoverBoard(char[][] sudoku) { + private boolean[][] initializeExactCoverBoard(int[][] board) { boolean[][] R = createExactCoverBoard(); - for (int i = 1; i <= S; i++) { - for (int j = 1; j <= S; j++) { - char n = sudoku[i - 1][j - 1]; - if (n != '.') { - for (int num = 1; num <= S; num++) { - if ((char) ('0' + num) != n) { + for (int i = COVER_START_INDEX; i <= BOARD_SIZE; i++) { + for (int j = COVER_START_INDEX; j <= BOARD_SIZE; j++) { + int n = board[i - 1][j - 1]; + if (n != NO_VALUE) { + for (int num = MIN_VALUE; num <= MAX_VALUE; num++) { + if (num != n) { Arrays.fill(R[getIndex(i, j, num)], false); } }