Fill a Matrix (2d array) recursively in Java - java

I have a Java programming assignment to do and in one of the questions, I have to fill a boolean 2d array (matrix) with "false" everywhere. I did it using two loops as following:
// The length and width are given
boolean [][] matrix;
matrix = new boolean [length][width];
int row;
int col;
for (row = 0; row < length; row++)
{
for (col = 0; col < width; col++)
{
matrix[row][col] = false;
}
}
The thing is that we just started the recursion chapter, and I would like if there is a way to do the same thing but this time using only recursion...
Thank you!

You can mimic the nested loop structure with recursion:
public static void fillWithFalse(boolean[][] array, int row) {
if (row < array.length) {
fillWithFalse(array[row], 0);
fillWithFalse(array, row + 1);
}
}
public static void fillWithFalse(boolean[] array, int col) {
if (col < array.length) {
array[col] = false;
fillWithFalse(array, col + 1);
}
}
or
public static void fillWithFalse(boolean[][] array, int row, int col) {
if (row < array.length) {
if (col < array[row].length) {
array[row][col] = false;
fillWithFalse(array, row, col + 1);
} else {
fillWithFalse(array, row + 1, 0);
}
}
}
Which is identical logic. But recursion is not good for this kind of thing and also to fill an array with false the correct solution is this:
boolean[][] matrix = new boolean[length][width];
Because boolean arrays will be default initialized with all elements as false. If the assignment is literally to fill a boolean array with false it may be basically a trick question because no action is necessary except to instantiate the array.

Well, not sure why is it necessary.. but.. here's my solution:
public static void insertFalse(boolean [][] arr,int row,int column)
{
if(row == 0&&column==0)
return ;
arr[row][column] = false;
if(column == 0)
insertFalse(arr,row-1,arr[0].length-1);
else
insertFalse(arr, row, column-1);
}

Related

How to use recursive backtracking to solve 8 queens? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
UPDATED CODE: My last question is how do I get it so that my program prints all 92 solutions of an 8x8 board, without any Queens attacking each other? So far, my code only prints 1 solution. For example, when I change it to a 4x4 board, I only have 1 solution, when there should be 2 I believe.
public class Queen{
public static void display(int[] board){
int n = board.length;
for(int column = 0; column < n; column++){
for(int row = 0; row < n; row++){
if(board[column] == row)
System.out.print('Q');
else
System.out.print('x');
}
System.out.print('\n');
}
}
public static int[] solveQueens(int n){
int board[] = new int[n];
placeQueen(board,0);
return board;
}
private static boolean placeQueen(int[] board, int column){
int n = board.length;
if (n == column){
return true;
}else{
for (int row = 0; row < n; row++){
int i; //remove
for (i = 0; i < column; i++){ //for (int i)
if (board[i] == row || i - column == board[i] - row || column - i == board[i] - row){
break;
}
}
if (i == column){
board[column] = row;
if (placeQueen(board, column + 1))
return true;
}
}
}
return false;
}
public static void main(String args[]){
int finished[] = solveQueens(8);
display(finished);
}
}
Now my programs returns:
Qxxxxxxx
xxxxQxxx
xxxxxxxQ
xxxxxQxx
xxQxxxxx
xxxxxxQx
xQxxxxxx
xxxQxxxx
OLD CODE:
I need to use recursive backtracking to solve the 8-queens problem. The n-queens problem is a puzzle that requires placing n chess queens on an n × n board so that none of the queens attack each other.
I need to Write a public solveQueens(int n) method to solve the problem for an nxn board
I also need to write a private recursive placeQueen(board, column) method to attempt to place a queen in the specified column.
This is my code so far:
public class Queen{
public static int[] solveQueens(int n){
int board[] = new int[n];
int finished[] = placeQueen(board,0);
return finished;
}
private static int[] placeQueen(int[] board, int column){
int n = board.length;
int row = column;
if (n == column){
return board;
}else{
for (row = n; row < n; row++){
board[column] = row;
if (board[n] == 0 && board[n-1] == 0 && board[n+1] == 0){
board[n] = 1;
placeQueen(board, column+1);
}
}
for (row = n; row < n; row++){
board[row] = column;
if (board[n] == 0 && board[n-1] == 0 && board[n+1] == 0){
board[n] = 1;
placeQueen(board, column+1);
}
}
}
return board;
}
public static void main(String args[]){
int finished[] = solveQueens(8);
for (int item: finished){
System.out.print(item);
}
}
}
Whenever I run my program, all it returns is
----jGRASP exec: java Queen
00000000
Is there any explanation on how to setup my 8x8 board, and how to place queens so they don't attack each other?
I made some changes in solveQueens and placeQueen:
public class Queen{
public static int[] solveQueens(int n){
int board[] = new int[n];
placeQueen(board,0); //it fills the board
return board;
}
private static boolean placeQueen(int[] board, int column){
int n = board.length;
int row;
if (n == column){
return true;
}else{
for (row = 0; row < n; row++){
int c;
for (c=0; c<column; c++){
if (board[c]==row || c-column==board[c]-row || column-c==board[c]-row){
//check if it is safe position (we know 2 queens couldn't place in a same column or row or diameter
break;
}
}
if (c==column){ //if previous loop didn't break...=> it is safe position
board[column]=row;
if (placeQueen(board, column+1)) //if it is possible to fill the rest of board //else: test the next row
return true;
}
}
}
return false;
}
public static void main(String args[]){
int finished[] = solveQueens(8);
for (int item: finished){
System.out.print(item);
}
}
}

managing references in parameter passing in java

A friend gave me a class that tries to solve sudoku puzzels. Thing is the changes of the array inside the method is not reflected in the original array. Here's the code:
public static void solve(int array[][], int row, int col)
{
if( row > 8 )
{
printBoard(array); // this gives the correct result
return;
}
if( array[row][col] != 0 )
nextEmptyCell(array, row, col );
else
{
for( int num = 1; num < 10; num++ )
{
if(validityRowColBox(array, row, col, num))
{
array[row][col] = num;
nextEmptyCell(array, row, col);
}
}
array[row][col] = 0;
}
}
public static void nextEmptyCell(int array[][], int row, int col)
{
if( col < 8 )
solve(array, row, col + 1 );
else
solve(array, row + 1, 0 );
}
//This boolean methods will checks the validity of the number for the given row, columns and its designated box.
public static boolean validityRowColBox(int array[][], int row, int col, int num)
{
for(int c = 0; c <9; c++ )
{
if( array[row][c] == num )
return false;// It return false if the number is already exist in the given row.
}
for(int r = 0; r <9; r++ )
{
if(array[r][col] == num )
return false;// It return false if the number is already exist in the given columns.
}
row = (row / 3) * 3 ;
col = (col / 3) * 3 ;
for( int r = 0; r < 3; r++ )
{
for( int c = 0; c < 3; c++ )
{
if( array[row+r][col+c] == num )
return false;// It return false if the number is already exist in the designated box.
}
}
return true;// Otherwise true.
}
// sample input
public static int[][] easy ()
{
return new int[][]
{{0,0,0,2,6,0,7,0,1},
{6,8,0,0,7,0,0,9,0},
{1,9,0,0,0,4,5,0,0},
{8,2,0,1,0,0,0,4,0},
{0,0,4,6,0,2,9,0,0},
{0,5,0,0,0,3,0,2,8},
{0,0,9,3,0,0,0,7,4},
{0,4,0,0,5,0,0,3,6},
{7,0,3,0,1,8,0,0,0}};
}
public static void main(String args[])
{
int inputArray[][] = easy();
solve(inputArray,0,0);
printBoard(inputArray); // items still the same!
}
}
If I call the printBoard(array); function inside the method, the elements of the array appears to change. But when I call the printBoard(array); method in the main method on the original array, the changes are lost, the values are back to original again. I am extremely confused by this. None of the methods creates a new object so it should still point to the inputArray object. What's happening?
Edit: Here's the printBoard() method
public static void printBoard(int array[][])
{
//This is the board method.
for (int row = 0; row < array.length; row++)
{
if (row % 3 == 0)//If the row is divisible by 3 then print the plus(+) and minus(-) sign.
System.out.println("+-------+-------+-------+");
for (int col = 0; col < array[row].length; col++) {
if (col % 3 == 0)// If the column is divisible by 3 then print the or(|) symbol.
System.out.print("| ");
System.out.print(array[row][col]+ " ");
}
System.out.println("|");
}
System.out.println("+-------+-------+-------+");
}
The problem is that when you come back from the various recursive calls there is an instruction that modify the content of the array (see the comments):
for( int num = 1; num < 10; num++ )
{
if(validityRowColBox(array, row, col, num))
{
array[row][col] = num;
nextEmptyCell(array, row, col); // after you finish you come back from here
}
}
array[row][col] = 0; // ...and this will change the solution you found
Apparently this cause the array to come back to his original state.
I didn't look how the program works but avoiding to execute that instruction if we found the solution will return the correct array, for example:
public static boolean solve(int array[][], int row, int col) {
if (row > 8) {
printBoard(array);
return true;
}
if (array[row][col] != 0) {
return nextEmptyCell(array, row, col);
}
for (int num = 1; num < 10; num++) {
if (validityRowColBox(array, row, col, num)) {
array[row][col] = num;
if (nextEmptyCell(array, row, col)) {
return true; // if solution is found we just exit
}
}
}
array[row][col] = 0;
return false;
}
public static boolean nextEmptyCell(int array[][], int row, int col) {
if (col < 8) {
return solve(array, row, col + 1);
}
return solve(array, row + 1, 0);
}

Unsure about the logic of the code

I cant test my method's code manually yet as Im not done with other associated code yet, but I feel like the logic of the method public boolean isFilledAt(int row, int col) is wrong. The method returns true if the shape has a filled block (any char) at the given row/col position and false if the block is empty(the dot '.'). If the position is out of bounds, raise a FitItException with an informative message. Could smb please look through it and let me know if anything is wrong with the method's code? Thanks!
public class CreateShape {
private int height;
private int width;
private char dc;
private Rotation initialPos;
private char[][] shape = new char[height][width];
public boolean isFilledAt(int row, int col)
{
if(row < 0 || row >= height || col < 0 || col >= width)
throw new FitItException("Oops! Out of bounds!");
else
{
for (int i = 0; i < shape.length; i++)
for (int j = 0; j < shape[i].length; j++) {
if (shape[row][col] == dc)
return true;
}
}
return false;
}
public boolean isFilledAt(int row, int col) {
if(row < 0 || row >= height || col < 0 || col >= width)
throw new FitItException("Oops! Out of bounds!");
else
return (shape[row][col] == dc);
}
does the same as your code currently does. I'm not sure what you are going through the array for, you're not even using the i and j variables.

Java count the size of chars in array

I have to write a program that will read a picture and then print out the number of blocks inside it.
I have to read the picture as a binary matrix of the size r × c (number of rows times number of
columns).
The blocks are groups of one or more adjacent elements with the value 1.
Blocks are built exclusively of elements with value 1
Each element with value 1 is a part of some block
Adjacent elements with value 1 belong to the same block.
We only take into account the horizontal and vertical adjacency but not diagonal.
INPUT:
In the first line of the input we have the integers r and c, separated with one space.
Then we have the r lines, where each contains s 0's and 1's.
The numbers inside the individual lines are NOT separated by spaces.
The OUTPUT only print the number of blocks in the picture.
For example:
EXAMPLE 1
INPUT:
7 5
01000
00010
00000
10000
01000
00001
00100
OUTPUT:
6
EXAMPLE 2:
INPUT:
25 20
00010000000000000000
00010000000000000000
00010000000000000100
00000000000000000100
00011111111000000100
00000000000000000100
00000000000000000100
00000000000000000100
00000000000000000100
01111111111000000100
00000000000000000100
00000000000000100100
00000000000000100100
00000000000000100100
01000000000000100000
01000000000000100000
01000000000000100000
01000000000000100000
00000000000000100000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00011111111111100000
00000000000000000000
OUTPUT:
7
THE PROBLEM:
The problem that I have is that my program only works for inputs such as in example 1.
So pictures that only consist of blocks of size 1. But it doesnt work if there are multiples 1's in a picture, such as EXAMPLE 2.
In example 2 where the output should be 7(Blocks are elements of 1.They can either be vertial or horizontal).... my programs output is 30.
I don't know how to adjust the program in a correct manner so it will give me the correct input.
Thank you for your help in advance, here is my code that I am posting bellow.
import java.util.Scanner;
class Blocks{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int rowNum=sc.nextInt();
int columnNum=sc.nextInt();
char[][] matrix = new char[rowNum][columnNum];
int nbrOfBlocks = 0;
for (int a = 0; a < rowNum; a++) {
matrix[a] = sc.next().toCharArray();
int index = 0;
while (index < matrix[a].length) {
if (matrix[a][index] == '1') {
++nbrOfBlocks;
while (index < matrix[a].length && matrix[a][index] == '1') {
++index;
}
}
++index;
}
}
System.out.println(nbrOfBlocks);
}
}
EDIT: Ok, here is a solution that will work for complex shapes
public class BlockCounter {
public static void main(String[] args) {
Board board = null;
try {
board = new Board("in3.txt");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
System.out.println("Block count: " + board.getBlockCount());
}
}
class Board {
ArrayList<String> data = new ArrayList<>();
boolean[][] used;
int colCount = 0;
public Board(String filename) throws FileNotFoundException, IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
data.add(line);
colCount = Math.max(colCount, line.length());
}
}
}
public int getBlockCount() {
used = new boolean[data.size()][colCount];
int count = 0;
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
used[row][col] = peek(row, col) == '1';
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
if (used[row][col]) {
fill(row, col);
count++;
}
used = null;
return count;
}
public char peek(int row, int col) {
if (row < 0 || row >= data.size() || col < 0)
return '0';
String rowData = data.get(row);
if (col >= rowData.length())
return '0';
return rowData.charAt(col);
}
public void fill(int row, int col) {
if (used[row][col]) {
used[row][col] = false;
if (row > 0 && used[row - 1][col])
fill(row - 1, col);
if (col > 0 && used[row][col - 1])
fill(row, col - 1);
if (col < colCount - 1 && used[row][col + 1])
fill(row, col + 1);
if (row < data.size() - 1 && used[row + 1][col])
fill(row + 1, col);
}
}
public int getRowCount() {
return data.size();
}
public int getColCount() {
return colCount;
}
}
Explanation:
When Board.getBlockCount() is called if creates a temporary array of booleans to work with so the original board is not messed up. Then it searches the entire board for "trues" (which correspond to '1's on the board). Every time a "true" is found, a flood fill algorithm clears the entire shape to which it is connected.
If you need more performance and less memory usage (specially stack) for larger boards, you can use another flood fill algorithm like in the example that follows. The big advantage here is that it doesn't use the stack for every pixel like the one above. It is considerably more complex though.
public class BlockCounter2 {
public static void main(String[] args) {
Board2 board = null;
try {
board = new Board2("in4.txt");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
System.out.println("Block count: " + board.getBlockCount());
}
}
class Board2 {
ArrayList<String> data = new ArrayList<>();
boolean[][] used;
Deque<Point> pointStack = new LinkedList<>();
int colCount = 0;
public Board2(String filename) throws FileNotFoundException, IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
data.add(line);
colCount = Math.max(colCount, line.length());
}
}
}
public int getBlockCount() {
used = new boolean[data.size()][colCount];
int count = 0;
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
used[row][col] = peek(row, col) == '1';
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
if (used[row][col]) {
fill(row, col);
count++;
}
used = null;
return count;
}
public char peek(int row, int col) {
if (row < 0 || row >= data.size() || col < 0)
return '0';
String rowData = data.get(row);
if (col >= rowData.length())
return '0';
return rowData.charAt(col);
}
public void fill(int row, int col) {
pointStack.push(new Point(col, row));
Point p;
while (pointStack.size() > 0) {
p = pointStack.pop();
fillRow(p.y, p.x);
}
}
private void checkRow(int row, int col, int minCol, int maxCol) {
boolean uu = false;
for (int x = col; x < maxCol; x++) {
if (!uu && used[row][x])
pointStack.add(new Point(x, row));
uu = used[row][x];
}
uu = true;
for (int x = col; x > minCol; x--) {
if (!uu && used[row][x])
pointStack.add(new Point(x, row));
uu = used[row][x];
}
}
private void fillRow(int row, int col) {
int lx, rx;
if (used[row][col]) {
for (rx = col; rx < colCount; rx++)
if (used[row][rx])
used[row][rx] = false;
else
break;
for (lx = col - 1; lx >= 0; lx--)
if (used[row][lx])
used[row][lx] = false;
else
break;
if (row > 0)
checkRow(row - 1, col, lx, rx);
if (row < data.size() - 1)
checkRow(row + 1, col, lx, rx);
}
}
public int getRowCount() {
return data.size();
}
public int getColCount() {
return colCount;
}
}
EDIT2: Both solutions were made using input from txt files in order to make the debugging and testing easier for larger arrays. If you need them to work with user input (the same you have in your code) as well, just make the following changes:
Change the main method so it will listen from user input (again):
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int rowNum=sc.nextInt();
int columnNum=sc.nextInt(); // Note columnNum is not necessary
String[] matrix = new String[rowNum]; // I hope char[][] is not a requirement
for (int a = 0; a < rowNum; a++) // Read array data from user input
matrix[a] = sc.next();
sc.close();
Board2 board = new Board2(matrix); // Call the new constructor
System.out.println("Block count: " + board.getBlockCount());
}
Add a new constructor to Board2, that takes a String[] as input:
public Board2(String[] data) {
for (String line : data) {
this.data.add(line);
colCount = Math.max(colCount, line.length());
}
}
You may remove the previous constructor Board2(String filename) if it is not useful for you but it's not necessary.
Are you searching for this:
import java.util.Scanner;
class Blocks {
public static void removeBlock(char[][] matrix, int posX, int posY) {
if(0 <= posX && posX < matrix.length
&& 0 <= posY && posY < matrix[posX].length) {
if(matrix[posX][posY] == '0') {
return;
}
matrix[posX][posY] = '0';
} else {
return;
}
removeBlock(matrix, posX - 1, posY);
removeBlock(matrix, posX + 1, posY);
removeBlock(matrix, posX, posY - 1);
removeBlock(matrix, posX, posY + 1);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// read in
char[][] matrix = new char[sc.nextInt()][sc.nextInt()];
for(int a = 0; a < matrix.length; a++) {
matrix[a] = sc.next().toCharArray();
}
// calculate number of blocks
int nrBlocks = 0;
for(int i = 0; i < matrix.length; i++) {
for(int j = 0; j < matrix[i].length; j++) {
if(matrix[i][j] == '1') {
// we have found a block, so increment number of blocks
nrBlocks += 1;
// remove any 1's of the block from the array, so that they each block is not counted multiple times
removeBlock(matrix, i, j);
}
}
}
System.out.println(nrBlocks);
}
}
There's a linear time (in number of cells) solution to this. If I get time, I'll add the code to this answer, but if not the Wikipedia article (see EDIT below) gives pseudo code.
The idea is to scan line-by-line, assigning an incrementing unique run numbers to each runs of 1s we see (and changing the cell content to be that unique number) If in any run, the cells immediately above in the previous line were also 1 (that is, they now have a run number), then we know that their unique-run-number and the current unique-run number form part of a single block. So record that the run-above-run-number, and the current-run-number are equivalent (but don't bother to change anything on the board)
At the end, we have a count of the runs we've seen. and a set of equivalence relationships of unique-run-numbers. For each set of equivalent-numbers (say runs 3, 5, 14 form a block), we subtract from the run count the number of runs, minus 1 (in other words, replacing the multiple runs with a single block count).
I think I have some ideas to mitigate the worst case, but they're probably not worth it.
And that's the number of blocks.
The worst case for the equivalence classes is O(size of board) though (1-wide vertical blocks, with one space between them will do this). Fortunately, the entirely-black board will need only O(height of board) - each row will get one number, which will be marked equivalent with the next row.
EDIT: There's a Stackoverflow question about this already: can counting contiguous regions in a bitmap be improved over O(r * c)?
and it turns out I've just re-invented the two-pass "Connected Component Labelling" algorithm discussed on Wikipedia

Java Bishop Chess Board

Im working on figuring out the maximum number of bishops I can place on a nxn board without them being able to attack each other. Im having trouble checking the Diagonals. below is my method to check the diagonals. The squares where a bishop currently is are marked as true so the method is supposed to check the diagonals and if it returns true then the method to place the bishops will move to the next row.
Im not quite sure whats going wrong, any help would be appreciated.
private boolean bishopAttack(int row, int column)
{
int a,b,c;
for(a = 1; a <= column; a++)
{
if(row<a)
{
break;
}
if(board[row-a][column-a])
{
return true;
}
}
for(b = 1; b <= column; b++)
{
if(row<b)
{
break;
}
if(board[row+b][column-b])
{
return true;
}
}
for(c = 1; b <= column; b++)
{
if(row<c)
{
break;
}
if(board[row+c][column+c])
{
return true;
}
}
return false;
}
for(c = 1; b <= column; b++)
Shouldn't it be
for(c = 1; c <= column; c++)
By the way:
1) Use i, j, k instead of a, b, c, etc. No REAL reason why... it's just convention.
2) You don't have to keep naming new variables. Try something like this:
for(int i = 1; i <= column; i++)
{
...
}
//because i was declared in the for loop, after the } it no longer exists and we can redeclare and reuse it
for(int i = 1; i <= column; i++)
{
...
}
3) Your error checking is incorrect. It should be something like this:
for(int i = 1; i < 8; i++)
{
int newrow = row - i;
int newcolumn = column - i;
if (newrow < 0 || newrow > 7 || newcolumn < 0 || newcolumn > 7)
{
break;
}
if (board[newrow][newcolumn])
{
return true;
}
}
Now when you copy+paste your for loop, you only have to change how newrow and newcolumn are calculated, and everything else (including loop variable name) will be identical. The less you have to edit when copy+pasting, the better. We also attempt all 7 squares so we don't have to change the ending condition - the if check within the loop will stop us if we attempt to go out of bounds in ANY direction.
4) Better still, of course, would be using the for loop only once and passing only the changing thing into it... something like...
private boolean bishopAttackOneDirection(int rowdelta, int coldelta, int row, int column)
{
for(int i = 1; i < 8; i++)
{
int newrow = row + rowdelta*i;
int newcolumn = column + columndelta*i;
if (newrow < 0 || newrow > 7 || newcolumn < 0 || newcolumn > 7)
{
break;
}
if (board[newrow][newcolumn])
{
return true;
}
}
return false;
}
private boolean BishopAttack(int row, int column)
{
return BishopAttackInOneDirection(-1, -1, row, column)
|| BishopAttackInOneDirection(1, -1, row, column)
|| BishopAttackInOneDirection(1, 1, row, column)
|| BishopAttackInOneDirection(-1, 1, row, column);
}
Probably not quite the expected answer, but there is no reason to make life more complex then it is.
Im working on figuring out the maximum number of bishops I can place on a nxn board without them being able to attack each other.
public int getMaximumNumberOfNonAttackingBishopsForSquareBoardSize(final int boardSize) {
if (boardSize < 2 || boardSize > (Integer.MAX_VALUE / 2))
throw new IllegalArgumentException("Invalid boardSize, must be between 2 and " + Integer.MAX_VALUE / 2 + ", got: " + boardSize);
return 2 * boardSize - 2;
}
Source: http://mathworld.wolfram.com/BishopsProblem.html

Categories

Resources