diff --git a/DIRECTORY.md b/DIRECTORY.md index 24cd22f67d07..af5905d00747 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -238,6 +238,7 @@ * [KnapsackMemoization](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/KnapsackMemoization.java) * [LevenshteinDistance](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/LevenshteinDistance.java) * [LongestAlternatingSubsequence](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/LongestAlternatingSubsequence.java) + * [LongestArithmeticSubsequence](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/LongestArithmeticSubsequence.java) * [LongestCommonSubsequence](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/LongestCommonSubsequence.java) * [LongestIncreasingSubsequence](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequence.java) * [LongestPalindromicSubsequence](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubsequence.java) @@ -733,6 +734,7 @@ * [KnapsackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/KnapsackTest.java) * [LevenshteinDistanceTests](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/LevenshteinDistanceTests.java) * [LongestAlternatingSubsequenceTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/LongestAlternatingSubsequenceTest.java) + * [LongestArithmeticSubsequenceTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/LongestArithmeticSubsequenceTest.java) * [LongestIncreasingSubsequenceTests](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceTests.java) * [LongestPalindromicSubstringTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstringTest.java) * [LongestValidParenthesesTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/LongestValidParenthesesTest.java) diff --git a/src/main/java/com/thealgorithms/others/Sudoku.java b/src/main/java/com/thealgorithms/others/Sudoku.java index 0839a376c5de..0e88aee46f4d 100644 --- a/src/main/java/com/thealgorithms/others/Sudoku.java +++ b/src/main/java/com/thealgorithms/others/Sudoku.java @@ -1,33 +1,47 @@ package com.thealgorithms.others; +/** + * A class that provides methods to solve Sudoku puzzles of any n x n size + * using a backtracking approach, where n must be a perfect square. + * The algorithm checks for safe number placements in rows, columns, + * and subgrids (which are sqrt(n) x sqrt(n) in size) and recursively solves the puzzle. + * Though commonly used for 9x9 grids, it is adaptable to other valid Sudoku dimensions. + */ final class Sudoku { + private Sudoku() { } + /** + * Checks if placing a number in a specific position on the Sudoku board is safe. + * The number is considered safe if it does not violate any of the Sudoku rules: + * - It should not be present in the same row. + * - It should not be present in the same column. + * - It should not be present in the corresponding 3x3 subgrid. + * - It should not be present in the corresponding subgrid, which is sqrt(n) x sqrt(n) in size (e.g., for a 9x9 grid, the subgrid will be 3x3). + * + * @param board The current state of the Sudoku board. + * @param row The row index where the number is to be placed. + * @param col The column index where the number is to be placed. + * @param num The number to be placed on the board. + * @return True if the placement is safe, otherwise false. + */ public static boolean isSafe(int[][] board, int row, int col, int num) { - // Row has the unique (row-clash) + // Check the row for duplicates for (int d = 0; d < board.length; d++) { - // Check if the number we are trying to - // place is already present in - // that row, return false; if (board[row][d] == num) { return false; } } - // Column has the unique numbers (column-clash) + // Check the column for duplicates for (int r = 0; r < board.length; r++) { - // Check if the number - // we are trying to - // place is already present in - // that column, return false; if (board[r][col] == num) { return false; } } - // Corresponding square has - // unique number (box-clash) + // Check the corresponding 3x3 subgrid for duplicates int sqrt = (int) Math.sqrt(board.length); int boxRowStart = row - row % sqrt; int boxColStart = col - col % sqrt; @@ -40,22 +54,37 @@ public static boolean isSafe(int[][] board, int row, int col, int num) { } } - // if there is no clash, it's safe return true; } + /** + * Solves the Sudoku puzzle using backtracking. + * The algorithm finds an empty cell and tries placing numbers + * from 1 to n, where n is the size of the board + * (for example, from 1 to 9 in a standard 9x9 Sudoku). + * The algorithm finds an empty cell and tries placing numbers from 1 to 9. + * The standard version of Sudoku uses numbers from 1 to 9, so the algorithm can be + * easily modified for other variations of the game. + * If a number placement is valid (checked via `isSafe`), the number is + * placed and the function recursively attempts to solve the rest of the puzzle. + * If no solution is possible, the number is removed (backtracked), + * and the process is repeated. + * + * @param board The current state of the Sudoku board. + * @param n The size of the Sudoku board (typically 9 for a standard puzzle). + * @return True if the Sudoku puzzle is solvable, false otherwise. + */ public static boolean solveSudoku(int[][] board, int n) { int row = -1; int col = -1; boolean isEmpty = true; + + // Find the next empty cell for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (board[i][j] == 0) { row = i; col = j; - - // We still have some remaining - // missing values in Sudoku isEmpty = false; break; } @@ -70,12 +99,12 @@ public static boolean solveSudoku(int[][] board, int n) { return true; } - // Else for each-row backtrack + // Try placing numbers 1 to n in the empty cell (n should be a perfect square) + // Eg: n=9 for a standard 9x9 Sudoku puzzle, n=16 for a 16x16 puzzle, etc. for (int num = 1; num <= n; num++) { if (isSafe(board, row, col, num)) { board[row][col] = num; if (solveSudoku(board, n)) { - // print(board, n); return true; } else { // replace it @@ -86,8 +115,17 @@ public static boolean solveSudoku(int[][] board, int n) { return false; } + /** + * Prints the current state of the Sudoku board in a readable format. + * Each row is printed on a new line, with numbers separated by spaces. + * + * @param board The current state of the Sudoku board. + * @param n The size of the Sudoku board (typically 9 for a standard puzzle). + */ public static void print(int[][] board, int n) { - // We got the answer, just print it + // Print the board in a nxn grid format + // if n=9, print the board in a 9x9 grid format + // if n=16, print the board in a 16x16 grid format for (int r = 0; r < n; r++) { for (int d = 0; d < n; d++) { System.out.print(board[r][d]); @@ -101,7 +139,13 @@ public static void print(int[][] board, int n) { } } - // Driver Code + /** + * The driver method to demonstrate solving a Sudoku puzzle. + * A sample 9x9 Sudoku puzzle is provided, and the program attempts to solve it + * using the `solveSudoku` method. If a solution is found, it is printed to the console. + * + * @param args Command-line arguments (not used in this program). + */ public static void main(String[] args) { int[][] board = new int[][] { {3, 0, 6, 5, 0, 8, 4, 0, 0}, @@ -117,7 +161,6 @@ public static void main(String[] args) { int n = board.length; if (solveSudoku(board, n)) { - // print solution print(board, n); } else { System.out.println("No solution");