My n Queens variation with an input seems to work for all inputs except 4x4 boards. It takes a board size and a starting position for 1 queen. Is there a reason why it isn't working for that size? I tried inputting 4 1 2 and it doesn't create a board properly
import java.io.*;
public class nQueens {
public static int N;
public static int skipCol;
public static int permaRow;
public static void printSolution(int board[][]) {
PrintWriter file = null;
try {
file = new PrintWriter("solution.txt");
// Prints Board to solution.txt
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (board[i][j] == 1) {
// If board = 1 then there is a Queen, 0 then empty
file.println((i + 1) + " " + (j + 1));
}
}
}
file.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static boolean isSafe(int board[][], int row, int col) {
// Returns True if safe, returns False if not safe
// Checks all columns in the row
int i,j;
for (i = 0; i < col; i++) {
if (board[row][i] == 1) {
return false;
}
}
// Check Diagonals (upper then lower)
for (i = row, j = col; i >= 0 && j >= 0; i--, j--) {
if (board[i][j] == 1) {
return false;
}
}
for (i = row, j = col; j >= 0 && i < N; i++, j--) {
if (board[i][j] == 1) {
return false;
}
}
return true;
}
public static boolean solveNQueensCol(int board[][], int col) {
if (col >= N) { // Base Case, checks if all queens are placed
return true;
}
if (col != skipCol) {
for (int i = 0; i < N; i++) {
if (isSafe(board, i, col)) {
board[i][col] = 1; // Changes that board space to Queen
if (solveNQueensCol(board, col + 1) == true) {
// Recursively places all the Queens onto the board
return true;
}
// If placing queen at i, col doesn't work, remove it
board[i][col] = 0;
}
}
} else {
board[permaRow][skipCol] = 1; // One Preset Queen
return solveNQueensCol(board,col+1);
}
return false;
}
public static boolean solveNQueens(int x, int y) {
// Creates new board with size N
int board[][] = new int[N][N];
for (int i = 0; i < N; i++) { // Fills board with 0s
for (int j = 0; j < N; j++) {
board[i][j] = 0;
}
}
permaRow = x;
skipCol = y;
if (solveNQueensCol(board, 0) == false) {
PrintWriter file = null;
try {
file = new PrintWriter("solution.txt");
// Prints Board to solution.txt
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (board[i][j] == 1) {
// If board = 1 then there is a Queen, 0 then empty
file.println((i + 1) + " " + (j + 1));
}
}
}
file.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
printSolution(board);
return true;
}
public static void main(String[] args) {
N = Integer.parseInt(args[0]);
solveNQueens(Integer.parseInt(args[1]) - 1, Integer.parseInt(args[2]) - 1);
}
}
If rows and columns are counted from 0 to 3, there is no solution when a queen starts in position 1,2.
Related
I've written the code as per the logic, but my Eclipse console is empty when I click 'Run'.
This is my code:
public class test {
public static void main(String[] args) {
int[][] board = new int[9][9];
helper(board, 0, 0);
}
public static void saveBoard(int[][] board) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
System.out.print(board[i][j]);
}
System.out.println();
}
}
public static void helper(int[][] board, int row, int col) {
if (row == board.length - 1) {
saveBoard(board);
return;
}
if (col == board.length - 1) {
col = 0;
row += 1;
}
for (int i = 1; i <= 9; i++) {
if (isSafe(board, row, col, i)) {
board[row][col] = i;
helper(board, row, col + 1);
}
}
}
public static boolean isSafe(int[][] board, int row, int col, int number) {
// row & column
for (int i = 0; i < board.length; i++) {
if (board[row][i] == number) return false;
if (board[i][col] == number) return false;
}
// grid
int sc = (col / 3) * 3;
int sr = (row / 3) * 3;
for (int i = 0; i < sr + 3; i++) {
for (int j = 0; j < sc + 3; j++) {
if (board[i][j] == number) return false;
}
}
return true;
}
}
or here's a screenshot
I'm trying to make a Sudoku game for my project but if i increase the number of empty spaces in the Sudoku Grid the code just throws an exception arrayoutofbounds but can't figure out where it's coming from. k is the number of empty spaces in the grid.
I haven't tried anything because can't figure out what can be done at this kind of problem
Here is the code:
package sudoku.puzzle;
import java.util.*;
public class SudokuPuzzle {
int[] mat[];
int N; // number of columns/rows.
int SRN; // square root of N
int K; // No. Of missing digits
// Constructor
SudokuPuzzle(int N, int K) {
this.N = N;
this.K = K;
// Compute square root of N
Double SRNd = Math.sqrt(N);
SRN = SRNd.intValue();
mat = new int[N][N];
}
// Driver code
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Select Level Of Difficulty \n 1.Easy\n 2.Medium\n 3.Hard");
String Choice = in .next(); in .close();
if ("1".equals(Choice) || "Easy".equals(Choice) || "easy".equals(Choice) || "e".equals(Choice) || "E".equals(Choice)) {
int N = 9, K = 40;
SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
sudoku.fillValues();
sudoku.printSudoku();
}
if ("2".equals(Choice) || "Medium".equals(Choice) || "medium".equals(Choice) || "m".equals(Choice) || "M".equals(Choice)) {
int N = 9, K = 60;
SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
sudoku.fillValues();
sudoku.printSudoku();
}
if ("3".equals(Choice) || "Hard".equals(Choice) || "hard".equals(Choice) || "h".equals(Choice) || "H".equals(Choice)) {
int N = 9, K = 72;
SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
sudoku.fillValues();
sudoku.printSudoku();
}
}
// Sudoku Generator
public void fillValues() {
// Fill the diagonal of SRN x SRN matrices
fillDiagonal();
// Fill remaining blocks
fillRemaining(0, SRN);
// Remove Randomly K digits to make game
removeKDigits();
}
// Fill the diagonal SRN number of SRN x SRN matrices
void fillDiagonal() {
for (int i = 0; i < N; i = i + SRN)
// for diagonal box, start coordinates->i==j
fillBox(i, i);
}
// Returns false if given 3 x 3 block contains num.
boolean unUsedInBox(int rowStart, int colStart, int num) {
for (int i = 0; i < SRN; i++)
for (int j = 0; j < SRN; j++)
if (mat[rowStart + i][colStart + j] == num)
return false;
return true;
}
// Fill a 3 x 3 matrix.
void fillBox(int row, int col) {
int num;
for (int i = 0; i < SRN; i++) {
for (int j = 0; j < SRN; j++) {
do {
num = randomGenerator(N);
}
while (!unUsedInBox(row, col, num));
mat[row + i][col + j] = num;
}
}
}
// Random generator
int randomGenerator(int num) {
return (int) Math.floor((Math.random() * num + 1));
}
// Check if safe to put in cell
boolean CheckIfSafe(int i, int j, int num) {
return (unUsedInRow(i, num) &&
unUsedInCol(j, num) &&
unUsedInBox(i - i % SRN, j - j % SRN, num));
}
// check in the row for existence
boolean unUsedInRow(int i, int num) {
for (int j = 0; j < N; j++)
if (mat[i][j] == num)
return false;
return true;
}
// check in the row for existence
boolean unUsedInCol(int j, int num) {
for (int i = 0; i < N; i++)
if (mat[i][j] == num)
return false;
return true;
}
// A recursive function to fill remaining
// matrix
boolean fillRemaining(int i, int j) {
// System.out.println(i+" "+j);
if (j >= N && i < N - 1) {
i = i + 1;
j = 0;
}
if (i >= N && j >= N)
return true;
if (i < SRN) {
if (j < SRN)
j = SRN;
} else if (i < N - SRN) {
if (j == (int)(i / SRN) * SRN)
j = j + SRN;
} else {
if (j == N - SRN) {
i = i + 1;
j = 0;
if (i >= N)
return true;
}
}
for (int num = 1; num <= N; num++) {
if (CheckIfSafe(i, j, num)) {
mat[i][j] = num;
if (fillRemaining(i, j + 1))
return true;
mat[i][j] = 0;
}
}
return false;
}
// Remove the K no. of digits to
// complete game
public void removeKDigits() {
int count = K;
while (count != 0) {
int cellId = randomGenerator(N * N);
// System.out.println(cellId);
// extract coordinates i and j
int i = (cellId / N);
int j = cellId % 9;
if (j != 0)
j = j - 1;
// System.out.println(i+" "+j);
if (mat[i][j] != 0) {
count--;
mat[i][j] = 0;
}
}
}
// Print sudoku
public void printSudoku() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
System.out.print(mat[i][j] + " ");
System.out.println();
}
System.out.println();
}
}
What you got is probably a ArrayIndexOutOfBoundsException. That means at some point you try to access a field of an array outside its boundaries.
But I canĀ“t see where K could be responsible for that. Can you provide more information about the error? E.g. at which value you get it or in which line.
EDIT: The variable i int the removeKDigits() function exceeds the boundaries of the array if the random generator spits out the value 81.
Can anyone tell me what is the more elegant solution for outputting this pattern?
I most interested in my makeTemplate method, but any other help will be appreciated.
Here is my code, which i want to be more readable:
public class Main {
public static void makeTemplate(char tab[][], int rows, int col) {
boolean increase = true;
int j = 0;
char star = '*';
for (int i = 0; i < rows; i++) {
if (increase) {
tab[i][j] = star;
if (j >= col - 1) {
increase = false;
j--;
continue;
}
j++;
} else {
tab[i][j] = star;
if (j < 0 + 1) {
increase = true;
j++;
continue;
}
j--;
}
}
}
public static void main(String[] args) {
char[][] tab = new char[30][6];
makeTemplate(tab, 30, 6);
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 6; j++) {
System.out.print(tab[i][j]);
}
System.out.println();
}
}
}
Only made some changes to makeTemplate
public static void makeTemplate(char tab[][], int rows, int col) {
boolean increase = true;
int j = 0;
char star = '*';
for (int i = 0; i < rows; i++) {
tab[i][j] = star;
if (increase) {
if (j >= col - 1) {
increase = false;
j--;
} else {
j++;
}
} else {
if (j < 1) {
increase = true;
j++;
}else {
j--;
}
}
}
}
Replaced the continue statements with else as the continue statement pretty much does the same thing as the else. Using continue in the if statement says to skip the j++ or j-- below. So instead the j++ or j-- will only be executed if the if is true.
I also changed if(j < 0 + 1) to if(j < 1) as 0+1 = 1
Moved tab[i][j] = star; before the first if as it is the first line in the if and else - Thanks Betlista
Elegant java8 solution:
IntStream.range(0, ROWS).forEach(i -> {
int cur = i % (COLS * 2);
if(cur < 6) {
IntStream.range(0, cur).forEach(f -> System.out.print(" "));
} else {
IntStream.range(0, COLS - cur % COLS).forEach(f -> System.out.print(" "));
}
System.out.println("*");
});
Granted, I haven't used the makeTemplate() method but as far as elegance and understand-ability goes, this does the job well.
You can use recursion
public static char[][] makeTemplate(char tab[][], int rows, int col, int curRow, int curPos, boolean increase) {
if (curRow == rows)
return tab;
tab[curRow][curPos] = '*';
if (increase && curPos + 1 == col) {
increase = false;
} else if (curPos == 0) {
increase = true;
}
return makeTemplate(tab, rows, col, curRow + 1, (increase) ? ++curPos : --curPos, increase);
}
public static void main(String[] args) {
char[][] tab = makeTemplate(new char[30][6], 30, 6, 0, 0, true);
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 6; j++) {
System.out.print(tab[i][j]);
}
System.out.println();
}
}
I want to check if the sum of each row in any matrix is equal. How should I rewrite this to avoid NPE?
I can make it work for "normal" matrices like int[][] a = {{1,2,3}, {4,5,6}}, but I want it to work even when testing with null and empty matrices.
public static boolean allRowSumsEqual(int[][] m) {
boolean a = false;
int x = 0;
int total = rowSum(m[0]);
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
x += m[i][j];
}
if (x != total) {
a = false;
break;
} else {
x = 0;
a = true;
}
}
return a;
}
public static int rowSum(int[] v) {
int vSum = 0;
for (int i = 0; i < v.length; i++) {
vSum += v[i];
}
return vSum;
}
As you said, this does work for most matrices. There are a few places I might check for null, see modified code below:
public static boolean allRowSumsEqual(int[][] m){
if(m == null) return true;
if(m.length == 0) return true;
boolean a = false;
int x = 0;
int total = rowSum(m[0]);
for (int i = 1; i < m.length; i++){
// You can use your own function instead of the inner for loop
x = rowSum(m[i]);
if (x != total) {
a = false;
break;
} else {
x = 0;
a = true;
}
}
return a;
}
public static int rowSum(int[] v){
int vSum = 0;
// Assume a null row has sum 0
if(v == null) return 0;
for (int i = 0 ; i < v.length ; i++){
vSum += v[i];
}
return vSum;
}
You need to define a result or an exception if you want to check for "null" parameter. You can return true if null is valid or false otherwise.
if(m == null) return true;
Empty or one lined matrices can return true all the time and does not require any calculation:
if(m.length < 2) return true;
The line test is more simple, I think:
// expect a positiv result
boolean result = true;
// calculate first line
int firstLine = rowSum(m[0]);
// loop remaining lines
for (int i = 1 ; i < m.length ; i++){
// compare first line with current line
if (firstLine != rowSum(m[i]))
{
// not equal -> change result
result = false;
// break loop
break;
}
}
return result;
public class Snippet {
public static boolean allRowSumsEqual(int[][] m) {
if (null == m || 0 == m.length)
return true;
boolean a = false;
int x = 0;
int total = 0;
if (null != m[0])
total = rowSum(m[0]);
for (int i = 1; i < m.length; i++) {
if (null != m[i]) {
for (int j = 0; j < m[i].length; j++) {
x += m[i][j];
}
} else
x = 0;
if (x != total) {
a = false;
break;
} else {
x = 0;
a = true;
}
}
return a;
}
public static int rowSum(int[] v) {
int vSum = 0;
for (int i = 0; i < v.length; i++) {
vSum += v[i];
}
return vSum;
}
public static void main(String[] args) {
int[][] a = { { 1, 2, 3 }, { 3, 2, 1 }, null };
System.out.println(allRowSumsEqual(a));
int[][] b = { null, null, null };
System.out.println(allRowSumsEqual(b));
}
}
What do you think of this solution:
public static boolean allRowSumsEqual(int[][] m) {
if(m == null) { return false; }
int sum = 0;
for(int i = 0; i < m.length; i++) {
int temp = 0;
if(m[i] == null) { continue; }
for(int j = 0; j < m[i].length; j++) {
temp += m[i][j];
}
if(i == 0) { //is the first row
sum = temp;
}
else if(sum != temp) {
return false;
}
}
return true;
}
public class Sudoku {
public static void main(String[] args) {
// Row and column Latin but with invalid subsquares
String config1 = "1234567892345678913456789124567891235678912346" + "78912345789123456891234567912345678";
String[][] puzzle1 = makeSudoku(config1);
if (isValidSudoku(puzzle1)) {
System.out.println("This puzzle is valid.");
} else {
System.out.println("This puzzle is invalid.");
}
System.out.println(getPrintableSudoku(puzzle1));
System.out.println("--------------------------------------------------");
// Row Latin but column not Latin and with invalid subsquares
String config2 = "12345678912345678912345678912345678912345678" + "9123456789123456789123456789123456789";
String[][] puzzle2 = makeSudoku(config2);
if (isValidSudoku(puzzle2)) {
System.out.println("This puzzle is valid.");
} else {
System.out.println("This puzzle is invalid.");
}
System.out.println(getPrintableSudoku(puzzle2));
System.out.println("--------------------------------------------------");
// A valid sudoku
String config3 = "25813764914698532779324685147286319558149273663" + "9571482315728964824619573967354218";
String[][] puzzle3 = makeSudoku(config3);
if (isValidSudoku(puzzle3)) {
System.out.println("This puzzle is valid.");
} else {
System.out.println("This puzzle is invalid.");
}
System.out.println(getPrintableSudoku(puzzle3));
System.out.println("--------------------------------------------------");
}
public static String[][] makeSudoku(String s) {
int SIZE = 9;
int k = 0;
String[][] x = new String[SIZE][SIZE];
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
x[i][j] = s.substring(k, k + 1);
k++;
}
}
return x;
}
public static String getPrintableSudoku(String[][] x) {
int SIZE = 9;
String temp = "";
for (int i = 0; i < SIZE; i++) {
if ((i == 3) || (i == 6)) {
temp = temp + "=================\n";
}
for (int j = 0; j < SIZE; j++) {
if ((j == 3) || (j == 6)) {
temp = temp + " || ";
}
temp = temp + x[i][j];
}
temp = temp + "\n";
}
return temp;
}
//sudoku validation
public static boolean isValidSudoku(String[][] x) {
return rowsAreLatin(x) && colsAreLatin(x) && goodSubsquares(x);
}
public static boolean rowsAreLatin(String[][] x) {
// fill in your code here
boolean result = true; // Assume rows are latin
for (int i = 0; i < 9; i++) {
result = result && rowIsLatin(x, i); // Make sure each row is latin
}
return result;
}
public static boolean rowIsLatin(String[][] x, int i) {
boolean[] found = new boolean[9];
for (int j = 0; j < 9; j++) {
found[Integer.parseInt(x[i][j])] = true;
}
for (int j = 0; j < 9; j++) {
if (!found[j]) {
return false;
}
}
return true;
}
public static boolean colsAreLatin(String[][] x) {
// fill in your code here
boolean result = true; // Assume cols are latin
for (int j = 0; j < 9; j++) {
result = result && colIsLatin(x, j); // Make sure each row is latin
}
return result;
}
public static boolean colIsLatin(String[][] x, int j) {
// fill in your code here
boolean[] found = new boolean[9];
for (int i = 0; i < 9; i++) {
found[Integer.parseInt(x[i][j])] = true;
}
for (int i = 0; i < 9; i++) {
if (!found[i]) {
return false;
}
}
return true;
}
public static boolean goodSubsquares(String[][] x) {
return true;
}
public static boolean goodSubsquare(String[][] x, int i, int j) {
boolean[] found = new boolean[9];
// We have a 3 x 3 arrangement of subsquares
// Multiplying each subscript by 3 converts to the original array subscripts
for (int p = i * 3, rowEnd = p + 3; p < rowEnd; p++) {
for (int q = j * 3, colEnd = q + 3; q < colEnd; q++) {
found[Integer.parseInt(x[p][q])] = true;
}
}
for (int p = 0; p < 9; p++) {
if (!found[p]) {
return false;
}
}
return true;
}
}
This the error I am getting. Help!
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
at Sudoku.rowIsLatin(Sudoku.java:104)
at Sudoku.rowsAreLatin(Sudoku.java:93)
at Sudoku.isValidSudoku(Sudoku.java:85)
at Sudoku.main(Sudoku.java:8)
Java Result: 1
The problem is with the line:
Integer.parseInt(x[i][j])
Sudoku numbers range from [1, 9], but indices for an array (of length 9) range from [0, 8]. So, when the (i, j) element is a 9, the index is 9 and therefore the IndexOutOfBoundsException is being thrown.
You'll have to change it to
found[Integer.parseInt(x[i][j]) - 1] = true;
Note that you also make the same mistake in the column's respective method.