I wrote a program to try to solve the 8 queens problem and one part of it required me to test all of the forward and backward diagonals to make sure there were no conflicts. I got the backwards to work perfectly but this part of the forward one was returning true while I was testing and I really can't figure out why. And help would be greatly appreciated :)
class NonAttackingQueen {
static char [][] board = { {'X','X','X','X','X','X','X','X'},
{'X','X','X','X','X','X','X','X'},
{'X','X','X','X','X','X','X','X'},
{'X','X','X','X','X','X','X','X'},
{'X','X','X','X','X','X','X','X'},
{'X','Q','X','X','X','X','X','X'},
{'Q','X','X','X','X','X','X','X'},
{'X','X','X','X','X','X','X','X'} };
public static boolean diagonalsClear () {
int numQueens;
boolean clear = true;
for (int numSpots = 1; numSpots < 9; numSpots++) {
numQueens = 0;
for (int row = 0; row < numSpots - 1; row++) {
if (board[row][numSpots - 1 - row] == 'Q')
numQueens++;
}
if (numQueens > 1) {
clear = false;
break;
}
}
for (int numSpots = 7; numSpots > 0; numSpots--) {
numQueens = 0;
for (int row = 7; row > 7 - numSpots; row--) {
if (board[row][15-row-numSpots] == 'Q')
numQueens++;
}
if (numQueens > 1) {
clear = false;
break;
}
return clear;
}
}
Little trick to solve this problem. It is obvious, that you have mistake with matrix row and column indices calculation, and your loops do not cover all cells in it. Easiest way to check it, just print it out to console. I can see, that you have problem with for (int row = 0; row < numSpots - 1; row++). Firs iteration, when numSpots=1 it skips this loop. Correct is for (int row = 0; row <= numSpots - 1; row++).
Let me give you some notes about your example. I can see that two upper and lower part of the matrix you check with opposite direction, upper one you start with row=0 and lower one - col=0. I think to do the same calculation is much better for understanding. You could decomposite you task into three simple once:
Check one single diagonal, starting with given row and column;
check upper diagonals;
check lower diagonals.
I think example below is more clear for reading:
private static boolean isDiagonalClear(int row, int col) {
int total = 0;
do {
if (board[row--][col++] == 'Q')
total++;
} while (total <= 1 && row >= 0 && col < 8);
return total <= 1;
}
public static boolean diagonalsClear() {
for (int row = 0; row < 7; row++)
if (!isDiagonalClear(row, 0))
return false;
for (int col = 0; col < 8; col++)
if (!isDiagonalClear(7, col))
return false;
return true;
}
Related
I'm having trouble with an algorithm, suppose the following:
A cinema has n rows, each row consists of m seats (n and m do not exceed 20). A two-dimensional matrix stores the information on the sold tickets, number 1 means that the ticket for this place is already sold, the number 0 means that the place is available. You want to buy k tickets to the neighboring seats in the same row. Find whether it can be done.
Input data
On the input, the program gets the number of n rows and m seats. Then, there are n lines, each containing m numbers (0 or 1) separated by spaces. The last line contains a number k.
Output data
The program should output the number of the row with k consecutive available seats. If there are several rows with k available seats, output the first row with these seats. If there is no such a row, output the number 0.
Code
import java.util.Scanner;
class Main {
static int findRowWithAvailableSeat(int[][] matrix, int tickets) {
final int rows = matrix.length;
final int columns = matrix[0].length;
int seatCounter = 0;
for (int r = 1; r <= rows; r++) {
for (int c = 1; c <= columns; c++) {
if (matrix[r][c] == 1) {
continue;
} if (matrix[r][c] == matrix[r][c + 1]) {
seatCounter++;
if (seatCounter == tickets) {
return r;
}
}
}
}
return 0;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int rows = scanner.nextInt();
int columns = scanner.nextInt();
int[][] matrix = new int[rows][columns];
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
matrix[r][c] = scanner.nextInt();
}
}
int kTickets = scanner.nextInt();
int rowWithAvailableSeats = findRowWithAvailableSeat(matrix, kTickets);
System.out.println(rowWithAvailableSeats);
}
}
I know the problem is somewhere in findRowWithAvailableSeat method. I would like a hint on how to solve the problem, not the actual solution. Thank you very much.
EDIT
I could finally solve it (or at least it works as intended, I'm not sure if it's the best implementation). Thanks you all for your tips.
static int findRowWithAvailableSeat(int[][] matrix, int tickets) {
final int rows = matrix.length;
final int columns = matrix[0].length;
int seatCounter;
for (int r = 0; r < rows; r++) {
seatCounter = 0;
for (int c = 0; c < columns; c++) {
if (matrix[r][c] == 1) {
seatCounter = 0;
continue;
}
if (matrix[r][c] == 0) {
seatCounter++;
if (seatCounter == tickets) {
return r + 1;
}
}
}
}
return 0;
}
Here are the 4 tips you need:
Don't compare matrix[r][c] == matrix[r][c + 1]. Plainly compare to 0:
matrix[r][c] == 0. To avoid ArrayIndexOutOfBoundsException
As DarkSigma already pointed, start your loops iterator from 0, not 1: for (int r = 0; r < rows...
Re-init your seatCounter to 0 for each row.
And! When you print out System.out.println(rowWithAvailableSeats), remember that row counting starts from 0.
Hope this helps
on main() method, you set matrix from index 0 to rows-1, and from index 0 to columns-1. But on findRowWithAvailableSeat(), you start from index 1. So index 0 will never be accessed.
} if (matrix[r][c] == matrix[r][c + 1]) { this line will try to access index c+1, will result index out of bound exception. either you need to check whether or not c+1 is less than column size or compare matrix[r][c] with 0 (matrix[r][c] == 0).
if you looking for neighboring seats, then you need to reset the seatCounter when you visit the sold seat (matrix[r][c] == 1)
you also need to reset seatCounter for each row.
I would put each row in a string and all rows in a string array a[m], then do a[i].contains(k) on each row:
"1001101110100010110010".contains("000")
Your for loops start at 1 instead of 0
for (int r = 1; r <= rows; r++) {
for (int c = 1; c <= columns; c++) {
if (matrix[r][c] == 1) {
The first index of the matrix array is being skipped. So you're not checking the first row and the first seat of each row.
Also, seatCounter is not being reset for each row. It currently retains any seats counted from previous rows.
I'm also not sure what this is for
if (matrix[r][c] == matrix[r][c + 1])
I'm writing a method that traverses through a 2d array in row-major order and at the start of each row, I initialize a count variable to zero. In the inner loop, if a value is non-zero I increment the count variable. At the end of the row, if the count variable is not exactly equal to 1, return false. Ive been working on this for about 2 weeks and can't find my error. Please point me in the right direction.
** Don't mind the print statements I'm trying to see how much the count is and my code only seems to hit the second row of the array
public static boolean isGPM(int[][] matrix) {
int count =0;
for (int row = 0; row < matrix.length; row++) {
count =0;
for (int col = 0; col < matrix[row].length; col++) {
if (matrix[row][col] > 0) {
count++;
}
else {
return !gpm;
}
}
}
System.out.println(count);
return gpm;
}
If I understand you correctly, you only care about the per-row count. This should work:
int count = 0;
// Process each row...
for (int row = 0; row < matrix.length; row++) {
count = 0;
// Process each column...
for (int col = 0; col < matrix[row].length; col++) {
// Check the cell.
if (matrix[row][col] != 0) {
count++;
}
}
// Row processing complete. Check count.
if (count != 1) {
System.out.println(count);
return gpm;
}
}
public static int[][] solve(int[][] input){
for (int i = 0; i < 9*9; i++){
if(input[i / 9][i % 9] != 0){
continue;
}
for (int j = 1; j <= 9; j++){
if(validNumber(input, i / 9, i % 9, j)){
input[i / 9][i % 9] = j;
solve(input);
}
}
}
return input;
}
This method should solve a (solvable) sudoku puzzle via backtracking regardless of the initial situation. It works like this:
Given a sudoku puzzle it iterates from the upper left corner over each row to the lower right corner of the 2D array. When there is already a number, it gets skipped. When there is a zero (empty field) it calculates possible values via the validNumber method. The first valid number (from 1 to 9) is put in the field and the method goes to the next field.
In this algorithm the method does not now whether or not a valid number will eventually render the puzzle unsolvable.
I want to alter it like this:
At the end, when the method finishes iterating through the whole 2d array, every entry of the array gets tested if it is a zero or not.
If there is even one zero the whole algorithm must go to the place where the very first "valid" number was put in. Now, the next "valid" number is put in and so on until there are no zeroes at the end of the algorithm.
I have some troubles implementing this thought. It seems to me there must be an other for loop somewhere, or something like a goto statement, but I don't know where to put it.
Any advice?
I implemented a Sudoku solver once before. It was a bit more complicated than what you had, but solved the game in a blink. :)
What you are attempting to do is solve Sudoku by "Brute Force" and using (tail) recursion. That means you are attempting to solve the board by iterating over all 981 possible combinations. 9 to the power of 81 is... well it's a big number. And so your approach will take eternity, but you'll run out of stack space from the tail recursion much sooner.
When I implemented Sudoko, it was more straight up. It kept a 9x9 array of "items", where each item was the value in the square, and an array of 9 booleans representing candidates (true == viable, false == eliminated). And then it just did a non-recursive loop of solving the board.
The main loop would start with the simple process of finding squares with only 1 remaining candidate. Then the next step would do simple candidate elimination based on values already assigned. Then it would work its way into more complicated elimination techniques such as X-Wing.
Your algorithm does not actually backtrack. It moves forward if it can, but it never moves backwards when it realizes it's stuck in a corner. This is because it never returns any knowledge up the stack, and it never resets squares. Unless you get really lucky, your code will get the game board into a cornered state, and then print out that cornered state. To backtrack, you need to reset the last square you set (the one that got you cornered) to zero, so your algorithm will know to keep trying other things.
For understanding backtracking, I highly recommend a book called The Algorithm Design Manual by Steven Skiena. I read it when I was preparing for SWE interviews, and it really improved my knowledge of backtracking, complexity, and graph search. The second half of the book is a catalog of 75 classic algorithmic problems, and Sudoku is one of them! He has an interesting analysis of optimizations you can make to prune the search tree and solve very hard puzzle boards. Below is some code I wrote a long time ago after reading this chapter (probably not that high quality by my current standards, but it works). I just read through it really quickly and added the solveSmart boolean in the solve method which allows you to turn one of those optimizations on or off, which results in a pretty big time savings when solving a "hard" class Sudoku board (one with only 17 squares filled in to start with).
public class Sudoku {
static class RowCol {
int row;
int col;
RowCol(int r, int c) {
row = r;
col = c;
}
}
static int numSquaresFilled;
static int[][] board = new int[9][9];
static void printBoard() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(" " + (board[i][j] == 0 ? " " : board[i][j]) + " ");
if (j % 3 == 2 && j < 8)
System.out.print("|");
}
System.out.println();
if (i % 3 == 2 && i < 8)
System.out.println("---------|---------|---------");
}
System.out.println();
}
static boolean isEntireBoardValid() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (!isBoardValid(i, j)) {
return false;
}
}
}
return true;
}
static boolean isRowValid(int row) {
int[] count = new int[9];
for (int col = 0; col < 9; col++) {
int n = board[row][col] - 1;
if (n == -1)
continue;
count[n]++;
if (count[n] > 1)
return false;
}
return true;
}
static boolean isColValid(int col) {
int[] count = new int[9];
for (int row = 0; row < 9; row++) {
int n = board[row][col] - 1;
if (n == -1)
continue;
count[n]++;
if (count[n] > 1)
return false;
}
return true;
}
static boolean isSquareValid(int row, int col) {
int r = (row / 3) * 3;
int c = (col / 3) * 3;
int[] count = new int[9];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int n = board[r + i][c + j] - 1;
if (n == -1)
continue;
count[n]++;
if (count[n] > 1)
return false;
}
}
return true;
}
static boolean isBoardValid(int row, int col) {
return (isRowValid(row) && isColValid(col) && isSquareValid(row, col));
}
static RowCol getOpenSpaceFirstFound() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == 0) {
return new RowCol(i, j);
}
}
}
return new RowCol(0, 0);
}
static RowCol getOpenSpaceMostConstrained() {
int r = 0, c = 0, max = 0;
int[] rowCounts = new int[9];
int[] colCounts = new int[9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] != 0)
rowCounts[i]++;
if (board[j][i] != 0)
colCounts[i]++;
}
}
int[][] squareCounts = new int[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int count = 0;
for (int m = 0; m < 3; m++) {
for (int n = 0; n < 3; n++) {
if (board[(i * 3) + m][(j * 3) + n] != 0)
count++;
}
}
squareCounts[i][j] = count;
}
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == 0) {
if (rowCounts[i] > max) {
max = rowCounts[i];
r = i;
c = j;
}
if (colCounts[j] > max) {
max = rowCounts[j];
r = i;
c = j;
}
}
}
}
return new RowCol(r, c);
}
static boolean solve() {
if (81 == numSquaresFilled) {
return true;
}
boolean solveSmart = true;
RowCol rc = solveSmart ? getOpenSpaceMostConstrained() : getOpenSpaceFirstFound();
int r = rc.row;
int c = rc.col;
for (int i = 1; i <= 9; i++) {
numSquaresFilled++;
board[r][c] = i;
if (isBoardValid(r, c)) {
if (solve()) {
return true;
}
}
board[r][c] = 0;
numSquaresFilled--;
}
return false;
}
public static void main(String[] args) {
// initialize board to a HARD puzzle
board[0][7] = 1;
board[0][8] = 2;
board[1][4] = 3;
board[1][5] = 5;
board[2][3] = 6;
board[2][7] = 7;
board[3][0] = 7;
board[3][6] = 3;
board[4][3] = 4;
board[4][6] = 8;
board[5][0] = 1;
board[6][3] = 1;
board[6][4] = 2;
board[7][1] = 8;
board[7][7] = 4;
board[8][1] = 5;
board[8][6] = 6;
numSquaresFilled = 17;
printBoard();
long start = System.currentTimeMillis();
solve();
long end = System.currentTimeMillis();
System.out.println("Solving took " + (end - start) + "ms.\n");
printBoard();
}
}
Eventually validNumber() method will not return any number because there is no possibilities left that means one of the previous choices was incorrect. Just imagine that the algorithm is started with the empty grid (obviously this puzzle is solvable1).
The solution is to keep tree of possible choices and if some choices are incorrect, then just remove them from the tree and use the next available choice (or step back on a higher level of the tree, if there is no choice left in this branch). This method should find a solution if any. (Actually this is how I implemented my sudoku solver some time ago.)
1 IMHO there are 3 different kinds of sudoku:
"true" correct sudoku that has a single unique complete solution;
ambiguous sudoku that has multiple distinct complete solutions, e.g. a puzzle with only 7 different numbers, so it has at least two distinct solutions that differ by swapping 8th and 9th numbers;
incorrect sudoku that has no complete solution, e.g. with a row with two or more occurrences of the same number.
With this definition, a solver algorithm should either:
prove that there is no solution;
return complete solution that satisfies the initial grid.
In the case of a "true" sudoku the result is a "true" solution by definition. In the case of an ambiguous sudoku the result can be different depending on the algorithm. An empty grid is the ultimate example of ambiguous sudoku.
I'm trying to test each row in my array to see if they are even or odd. If the row is even i want to change the random value in the elements of the row to 0. If the row is odd i want to change the elements to 1. Ive been able to create the element and print it out but im stuck on how to test the rows. I know to test if a number is even you use (i % 2 == 0) but im not sure what coding i should use.
public static void main(String[] args) {
int[][] box;
box = new int[2][2];
int row;
int column;
for (row = 0; row < box.length; row++) {
for (column = 0; column < box[row].length; column++) {
box[row][column] = (int) (Math.random() * 100);
}
}
//where im having issues
// i get error 'bad operand types for binary operator'
if (box[row] % 2 == 0) {
for (row = 0; row< box.length;row++){
box[row][column] = [0][];
}
}
else{
for(row = 0; row < box.length; row++){
box[row][column] = [1][];
}
}
for (row = 0; row < box.length; row++) {
for (column = 0; column < box[row].length; column++) {
System.out.print(box[row][column] + " ");
}
System.out.println();
}
}
}
you can use Arrays built in function fill(int[],value) that takes two argument, First 1d array and second a value to fill
//also if you are checking is row is even or odd divide row not box[row]
if (row % 2 == 0) {
Arrays.fill(box[row],0);//set 0 to every element in this wor
}
else{
Arrays.fill(box[row],1);//set 1 to every element in this wor
}
Hi I am trying to create a matrix on the console using 2D array. The idea is that the output should look like this one :
1|8|9 |16
2|7|10|15
3|6|11|14
4|5|12|13
Is there any one who has an idea how it can be done?
Few things you can guess from the matrix: -
First, you have to traverse all rows of a columns first before moving to the next column
Second, you need to alternate between downwards and upwards direction on each iteration
So, you would need two nested for loop, for iterating through rows for a particular column. One will go from row 0 to max - 1, and the next will go from row = max - 1 to 0.
Now, to alternate the iteration direction, you can use a boolean variable, and toggle it after each iteration of inner loop finishes.
Each loop needs to be enclosed inside an if-else. Both of them will be executed on a certain condition. If boolean downwards = false;, then loop moving upwards will be executed and vice-versa.
On each iteration, fill the current cell with an integer counter, that you would have to initialize with 1, and increment it after each fill.
Pseudo code : -
// Initialize variables row, col, and count = 1
boolean goDown = true;
int[][] matrix = new int[row][col]; // declare matrix
for i = 0 to col:
if (goDown)
for j = 0 to row: // Move in downwards direction
assign count++ to matrix[j][i]
// assign to `[j][i]` because, we have to assign to rows first
goDown = false; // Toggle goDown
else
for j = row - 1 to 0: // Move in upwards direction
assign count++ to matrix[j][i]
goDown = true; // toggle goDown
}
Just some psuedo-code, hope it helps and gives you something to start with.
boolean goUp = false;
boolean goDown = true;
size = 4;
matrix[size][size];
k = 0;
l =0;
loop i->0 i < size*size i++
matrix[l][k] = i;
if(l==size and goDown)
goDown = false;
goUp = true;
k++;
else if(l==0 and goUp)
goDown = true;
goUp = false;
k++;
else
l = l+ (1*goDown?1:-1);
end loop;
finally with your help and after looking carefully at how multidimensional arrays work I solved the problem which now is looking quite simple to me.
int a = 4;
int b = 4;
int c = 1;
boolean direction = true;
int[][] arrey = new int[a][b];
for (int y = 0; y <= b - 1; y++) {
if (direction) {
for (int x = 0; x <= a - 1; x++) {
arrey[x][y] = c;
c++;
}
direction = false;
} else {
for (int x = a - 1; x >= 0; x--) {
arrey[x][y] = c;
c++;
}
direction = true;
}
}
for (int x = 0; x <= a - 1; x++) {
for (int y = 0; y <= b - 1; y++) {
System.out.print("["+arrey[x][y]+"]");
}
System.out.println("");
}
const matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
];
let i = 1;
for (let col = 0; col < matrix[0].length; col++) {
if (col % 2 === 1) {
for (let row = matrix.length - 1; row >= 0; row--) {
matrix[row][col] = i++;
}
} else {
for (let row = 0; row < matrix.length; row++) {
matrix[row][col] = i++;
}
}
}
console.table(matrix);