Flood fill for 2d int array optimization in Java - java

I am writing my own implementation of the Flood Fill.
I came up with this code:
public static void fillArea(int x, int y, int original, int fill, int[][] arr) {
Stack<int[]> q = new Stack<int[]>();
int[] w = new int[2]; //to the west
int[] e = new int[2]; //to the east
if (arr[x][y] != original) {
return;
}
q.push(new int[]{x, y});
while (!q.isEmpty()) {
int[] pos = (int[]) q.pop();
int i = pos[0];
int j = pos[1];
if (arr[i][j] == original) {
e[0] = i;
e[1] = j;
w[0] = i;
w[1] = j;
}
while (w[1] > 0 && arr[w[0]][w[1] - 1] == original) { // to the west
w[1] -= 1;
}
while (e[1] < arr[0].length - 1 && arr[e[0]][e[1] + 1] == original) { // to the east
e[1] += 1;
}
for (int a = w[1]; a <= e[1]; a++) { // for every point between west and east
arr[w[0]][a] = fill;
if (w[0] > 0 && arr[w[0] - 1][a] == original) { //check if we can go north
q.push(new int[]{(w[0] - 1), a});
}
if (w[0] < arr.length - 1 && arr[w[0] + 1][a] == original) {//check if we can go south
q.push(new int[]{(w[0] + 1), a});
}
}
}
return;
}
Params are:
start point coords, value we want to change, new value we want to see as a result of filling, original array.
It is implementation of Wiki pseudocode:
Flood-fill (node, target-color, replacement-color):
1. Set Q to the empty queue.
2. If the color of node is not equal to target-color, return.
3. Add node to Q.
4. For each element N of Q:
5. If the color of N is equal to target-color:
6. Set w and e equal to N.
7. Move w to the west until the color of the node to the west of w no longer matches target-color.
8. Move e to the east until the color of the node to the east of e no longer matches target-color.
9. For each node n between w and e:
10. Set the color of n to replacement-color.
11. If the color of the node to the north of n is target-color, add that node to Q.
12. If the color of the node to the south of n is target-color, add that node to Q.
13. Continue looping until Q is exhausted.
14. Return.
I am using Stack instead of Queue, because it seems that Stack is much faster, or I have a problem with my code.
The problem is : it is very slow.
Is there anything I can do about performance? I can trade memory for the performance, but native recursion get me stackoverflow.

Ok, here we go :).
I simulated stack with array, which I hope would be much faster. I did not followed exactly the pseudocode, but it works and I think it should be fast.
public static void main(String[] args) {
int testArray[][] = new int[10][10];
for (int i = 0; i < 10; i++) {
testArray[i][i] = 1;
testArray[9-i][i] = 1;
}
testArray[4][7] = 1;
System.out.println("Array before");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.print(testArray[j][i] + " ");
}
System.out.println("");
}
fillArea(6,8,0,7,testArray);
System.out.println("Array after");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.print(testArray[j][i] + " ");
}
System.out.println("");
}
}
public static void fillArea(int x, int y, int original, int fill, int[][] arr) {
int maxX = arr.length - 1;
int maxY = arr[0].length - 1;
int[][] stack = new int[(maxX+1)*(maxY+1)][2];
int index = 0;
stack[0][0] = x;
stack[0][1] = y;
arr[x][y] = fill;
while (index >= 0){
x = stack[index][0];
y = stack[index][1];
index--;
if ((x > 0) && (arr[x-1][y] == original)){
arr[x-1][y] = fill;
index++;
stack[index][0] = x-1;
stack[index][1] = y;
}
if ((x < maxX) && (arr[x+1][y] == original)){
arr[x+1][y] = fill;
index++;
stack[index][0] = x+1;
stack[index][1] = y;
}
if ((y > 0) && (arr[x][y-1] == original)){
arr[x][y-1] = fill;
index++;
stack[index][0] = x;
stack[index][1] = y-1;
}
if ((y < maxY) && (arr[x][y+1] == original)){
arr[x][y+1] = fill;
index++;
stack[index][0] = x;
stack[index][1] = y+1;
}
}
}
This code having this output :
Array before
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 1 0 0 1 0 0 0
0 0 1 0 1 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 0 1
Array after
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 1 7 7 1 0 0 0
0 0 1 7 1 7 7 1 0 0
0 1 7 7 7 7 7 7 1 0
1 7 7 7 7 7 7 7 7 1

This version is even faster
public static void floodFill(int y, int x, byte originalvalue, byte newvalue, byte[][] arr) {
Deque queue = new ArrayDeque();
queue.add(new int[]{y, x});
while (!queue.isEmpty()) {
int[] t = (int[]) queue.poll();
y = t[0];
x = t[1];
if (arr[y][x] == originalvalue) {
arr[y][x] = newvalue;
for (int i = 0; i
< 8; i++) {
if (x + dx[i] < arr[0].length && y + dy[i] < arr.length && x + dx[i] > -1 && y + dy[i] > -1 && arr[y + dy[i]][x + dx[i]] == originalvalue) {
queue.add(new int[]{y + dy[i], x + dx[i]});
}
}
}
}
}

Related

Counting adjacent -1s in a 2d array without checking positions that are out of bounds (Minesweeper)

I am in the process of writing a program that works like Minesweeper. This is done in a 10x10 2d-array, and since I'm working with constraints, I can only write this using a 2d-array. However, I am getting a logical error with my count() method. The count() method returns the number of -1s found in the grid surrounding the input position (input position is what I'd make row and column in main(), for example, (5, 5). It also must not check a position outside the bounds of the 2d array. Here is a visual of what the output of count() should look like.
I also have to use count() with setCounts(). setCounts() goes through the entire 2d array, skips any position that is a -1, and calls the count() method, setting the current position to the value the count() method returns.
public int count(int row, int col)
{
int value = 0;
for(int r = -1; r < 2; r++)
{
for(int c = -1; c < 2; c++)
{
if(c == 0 && r == 0)
continue;
int newR = row + c;
int newC = col + c;
if(newR < 0 || newR >= array.length && newC < 0 || newC >= array[0].length)
continue;
if(array[newR][newC] == -1)
value++;
}
}
return value;
}
public void setCounts()
{
for(int r = 0; r < array.length; r++)
{
for(int c = 0; c < array[r].length; c++)
{
if(array[r][c] != -1)
array[r][c] = count(r, c);
String formatted = String.format("%2d", array[r][c]);
System.out.print(formatted + " ");
}
System.out.println();
}
}
The problem is that:
The count() method is incorrectly counting adjacent -1s surrounding any position I put in main()
setCounts() goes out of bounds after printing a random number of rows
I am certain that it has to do with this block of code:
if(newR < 0 || newR >= array.length && newC < 0 || newC >= array[0].length)
continue;
if(array[newR][newC] == -1)
value++;
When I printed newR and newC in the loop after continue, the loop is randomly adding more numbers to a row/column combo with no direct pattern for the entire output when count() was called in setCounts():
00
11
11
00
11
0 01
12
12
01
12
0 02
13
13
02
13
0 03
14
14
03
14
3 04
15
15
04
15
0 -1 -1 -1 -1 09
09
0
-1 00
...
So taking the print statements out, I get this as an output:
0 -1 -1 0 -1 -1 -1 0 0 0
0 0 0 0 0 0 -1 0 0 0
0 -1 0 -1 0 0 0 0 0 0
0 0 -1 0 0 0 0 0 -1 0
-1 0 0 0 -1 0 0 0 0 0
0 0 0 -1 0 0 0 -1 0 0
0 0 0 0 0 0 -1 0 -1 0
0 0 0 0 -1 -1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
there are 0 -1s
-----------
3 3 0 -1 3 3 0 -1 0 0
/* Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
at Grid3.count(Grid3.java:44)
at Grid3.setCounts(Grid3.java:58)
at Grid3.main(Grid3.java:86) */
The first array is the array I make with Grid's constructor. The second array that the program is trying to print is being done when setCounts() is called.
I was thinking that changing it to:
if(newR < 0 || newR >= array.length)
continue;
if(newC < 0 || newC >= array[0].length)
continue;
if(array[newR][newC] == -1)
value++;
would work: and it does, but not logically. It gets rid of the ArrayIndexOutOfBoundsException error, but logically does not work since it doesn't count adjacent -1's right. It also seems to be adding more numbers randomly to any row/column combo. I put the position as (5, 5) in main() and one time I ran the code, it counted 6 -1s but there are only 3 -1s in the position I put:
-1 0 0 0 0 -1 0 -1 0 0
0 0 0 0 -1 -1 0 0 0 0
0 -1 0 0 0 0 0 0 0 0
0 -1 0 -1 -1 0 0 -1 -1 0
0 0 0 -1 -1 -1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
-1 0 0 0 0 0 -1 0 0 0
0 -1 0 0 0 -1 0 0 0 0
0 -1 0 0 -1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
there are 6 -1s
And for setCounts(), it printed a full 10x10 2d array but does not count -1s properly either. For the position (0, 0) (in this case, the 3 at the top left corner of the output shown below), that position should actually have a value of 2 since there are only 2 adjacent -1s, but it actually counts 3.
3 0 0 0 0 0 -1 0 0 0
-1 -1 0 3 0 0 0 -1 0 0
-1 3 6 3 -1 0 3 0 3 0
0 3 0 -1 -1 -1 0 -1 0 0
3 0 0 0 -1 3 6 3 3 0
3 -1 0 0 0 3 0 -1 -1 0
-1 -1 3 0 0 0 0 3 3 3
0 6 6 0 3 0 0 0 -1 0
0 0 -1 -1 0 -1 0 0 0 3
0 0 0 3 3 0 3 0 0 0
Here is a full output:
0 0 0 0 0 0 -1 0 0 0
0 -1 0 0 -1 0 0 0 0 0
0 -1 0 0 0 -1 0 0 0 0
0 0 -1 -1 -1 0 0 -1 0 0
0 0 0 0 0 -1 -1 0 -1 0
-1 0 0 -1 0 -1 0 0 0 0
0 0 0 0 0 0 0 0 -1 0
0 -1 0 0 0 0 0 0 -1 0
0 0 0 0 0 0 -1 0 -1 0
0 0 0 0 0 0 0 0 0 0
there are 2 -1's
-----------
3 0 0 3 0 0 -1 0 0 0
3 -1 0 0 -1 0 0 3 0 0
0 -1 6 3 0 -1 3 0 0 0
0 0 -1 -1 -1 3 3 -1 0 0
0 0 3 3 6 -1 -1 0 -1 0
-1 0 0 -1 0 -1 3 6 0 3
3 3 0 0 3 0 3 3 -1 0
0 -1 0 0 0 3 0 3 -1 3
0 0 3 0 0 0 -1 0 -1 3
0 0 0 0 0 0 0 3 0 3
I cannot figure out what I'm doing wrong. I need count() to properly count adjacent -1s given a position. If it doesn't count adjacent -1s properly, then setCounts() will not logically work. What should I change in either or both methods so that it properly and logically works? Here is my code so far.
public class Grid
{
private int [][] array;
private int max;
public Grid(int max)
{
array = new int[10][10];
this.max = max;
setRandom();
}
public void setRandom()
{
int i = 0;
while(i < max)
{
int r = (int)(Math.random() * 9) + 0;
int c = (int)(Math.random() * 9) + 0;
if(array[r][c] != -1)
{
array[r][c] = -1;
i++;
}
}
}
public int count(int row, int col)
{
int value = 0;
for(int r = -1; r < 2; r++)
{
for(int c = -1; c < 2; c++)
{
if(c == 0 && r == 0)
continue;
int newR = row + c;
int newC = col + c;
if(newR < 0 || newR >= array.length && newC < 0 || newC >= array[0].length)
continue;
if(array[newR][newC] == -1)
value++;
}
}
return value;
}
public void setCounts()
{
for(int r = 0; r < array.length; r++)
{
for(int c = 0; c < array[r].length; c++)
{
if(array[r][c] != -1)
array[r][c] = count(r, c);
String formatted = String.format("%2d", array[r][c]);
System.out.print(formatted + " ");
}
System.out.println();
}
}
public void print()
{
for(int r = 0; r < array.length; r++)
{
for(int c = 0; c < array[r].length; c++)
{
System.out.print(array[r][c] + " ");
}
System.out.println();
}
}
public static void main(String[] args) // printing grid
{
Grid first = new Grid(20);
int count = first.count(5, 5);
first.print();
System.out.println("there are " + count + " -1s");
System.out.println("-----------");
first.setCounts();
}
}
It might be easier to not use a 2d-array.
Or at least, you might want to store an object representing each cell rather than just an int. This way, you could implement the logic for figuring out the neighboring cells for a particular cell within the Cell-Class.
Here is an example (using a map instead of an array):
public class Grid {
public final int width, height;
private final Map<Coordinate, Cell> cells;
public Grid(int width, int height) {
this.width = width;
this.height = height;
this.cells = IntStream.range(0, width).boxed()
.flatMap(column ->
IntStream.range(0, height).boxed()
.map(row -> new Coordinate(row, column))
)
.map(Cell::new)
.collect(Collectors.toMap(Cell::getCoordinate, Function.identity()));
}
public Cell get(int row, int col) {
return this.cells.get(new Coordinate(row, col));
}
public class Cell {
private final Coordinate coordinate;
private final boolean isMine;
public Cell(Coordinate coordinate, boolean isMine) {
this.coordinate = coordinate;
this.isMine = isMine;
}
public Cell(Coordinate coordinate) {
this(coordinate, new Random().nextBoolean());
}
public Coordinate getCoordinate() {
return coordinate;
}
public List<Cell> getNeighbours() {
int leftNeighbourColumnIdx = coordinate.column - 1;
int topNeighbourRowIdx = coordinate.row - 1;
return IntStream.range(leftNeighbourColumnIdx, leftNeighbourColumnIdx + 3).boxed()
.flatMap(column -> IntStream.range(topNeighbourRowIdx, topNeighbourRowIdx + 3).boxed().map(row -> new Coordinate(row, column)))
.map(Grid.this.cells::get)
.filter(Objects::nonNull)
.filter(c -> !c.equals(this))
.collect(Collectors.toList());
}
public int countNeighbouringMines() {
return (int) getNeighbours().stream()
.filter(cell -> cell.isMine)
.count();
}
}
public static class Coordinate {
private final int row, column;
public Coordinate(int row, int column) {
this.row = row;
this.column = column;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Coordinate that = (Coordinate) o;
return row == that.row && column == that.column;
}
#Override
public int hashCode() {
return Objects.hash(row, column);
}
}
public static void main(String[] args) {
final var grid = new Grid(10, 10);
for (int row = 0; row < grid.height; row++) {
for (int col = 0; col < grid.width; col++) {
final var cell = grid.get(row, col);
System.out.print(cell.isMine ? "x" : "o");
System.out.print(" ");
}
System.out.println();
}
System.out.printf("mines around (5,5): %d%n", grid.get(5, 5).countNeighbouringMines());
}
}
Edit: same example as above but with a 2d-array instead of a map
public class Grid {
public final int width, height;
private final Cell[][] cells;
public Grid(int width, int height) {
this.width = width;
this.height = height;
cells = new Cell[width][height];
IntStream.range(0, width)
.forEach(column -> IntStream.range(0, height)
.forEach(row -> cells[column][row] = new Cell(column, row))
);
}
public Cell get(int row, int col) {
final var column = col < 0 || col >= this.cells.length ? null : this.cells[col];
return row < 0 || column == null || row >= column.length ? null : column[row];
}
public class Cell {
private final int column, row;
private final boolean isMine;
public Cell(int column, int row, boolean isMine) {
this.column = column;
this.row = row;
this.isMine = isMine;
}
public Cell(int column, int row) {
this(column, row, new Random().nextBoolean());
}
public List<Cell> getNeighbours() {
int leftNeighbourColumnIdx = column - 1;
int topNeighbourRowIdx = row - 1;
return IntStream.range(leftNeighbourColumnIdx, leftNeighbourColumnIdx + 3).boxed()
.flatMap(column -> IntStream.range(topNeighbourRowIdx, topNeighbourRowIdx + 3).boxed()
.map(row -> Grid.this.get(row, column)))
.filter(Objects::nonNull)
.filter(c -> !c.equals(this))
.collect(Collectors.toList());
}
public int countNeighbouringMines() {
return (int) getNeighbours().stream()
.filter(cell -> cell.isMine)
.count();
}
}
public static void main(String[] args) {
final var grid = new Grid(10, 10);
for (int row = 0; row < grid.height; row++) {
for (int col = 0; col < grid.width; col++) {
final var cell = grid.get(row, col);
System.out.print(cell.isMine ? "x" : "o");
System.out.print(" ");
}
System.out.println();
}
System.out.printf("mines around (5,5): %d%n", grid.get(5, 5).countNeighbouringMines());
}
}
The idea is, that the get(int row, int col) method in Grid returns either a Cell object or null if row or cell are invalid -- but it never fails (throws an exception).
Every cell can then use this method to try to get all its neighbours (getNeighbours()).
The cell doesn't need to worry, if the row/column it asks for is valid or not -- this will be handled by get(int row, int col).
It just needs to filter out all null values (those coordinates were invalid) and itself.
With getNeighbours(), you have a list with all the neighboring cells. If you filter out all cells which have no mines - you get a list of neighbours with mines on them -- and then you just need to count them.

Drawing a diamond of numbers in a 2d array Java

I've been solving some coding questions to get myself prepared for a coding interview, and found out a question that seemed kind of puzzling. I solved the question after spending some time on it; however, the code looks hardcoded and has no style. So, I was wondering if I could get some feedbacks on styling the code, or perhaps getting an better idea of approaching the problem.
The question basically asks you to draw a diamond of numbers with a pattern in 2d array.
It gives a coordinate of 'x' and range of x. From the x, the numbers spread one by one until the range. So, there are 4 different inputs, N (the size of an array), X, Y (the coordinate of 'x' as (rows, cols)), and R (range).
If they were given a size of 8, coordinate of (4,5) with a range of 3, the result would be like,
0 0 0 0 3 0 0 0
0 0 0 3 2 3 0 0
0 0 3 2 1 2 3 0
0 3 2 1 x 1 2 3
0 0 3 2 1 2 3 0
0 0 0 3 2 3 0 0
0 0 0 0 3 0 0 0
0 0 0 0 0 0 0 0
And the below is what I have,
int n = sc.nextInt();
char[][] arr = new char[n][n];
int r = sc.nextInt() - 1;
int c = sc.nextInt() - 1;
int range = sc.nextInt();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
arr[i][j] = '0';
}
}
arr[r][c] = 'x';
int num = 1;
for (int i = 0; i < range; i++) {
//Cross
if (c-num > -1) {
arr[r][c - num] = (char) (num + '0');
}
if (c+num < n) {
arr[r][c + num] = (char) (num + '0');
}
if (r-num > -1) {
arr[r - num][c] = (char) (num + '0');
}
if (r+num < n) {
arr[r + num][c] = (char) (num + '0');
}
//Diagonal
if (i > 0) {
int sum = num - 1, delta = 1;
while (sum != 0) {
if (r-sum > -1 && c+delta < n) {
arr[r - sum][c + delta] = (char) (num + '0');
}
sum--;
delta++;
}
sum = num - 1; delta = 1;
while (sum != 0) {
if (r+sum < n && c-delta > -1) {
arr[r + sum][c - delta] = (char) (num + '0');
}
sum--;
delta++;
}
sum = num - 1; delta = 1;
while (sum != 0) {
if (r-sum > -1 && c-delta > -1) {
arr[r - sum][c - delta] = (char) (num + '0');
}
sum--;
delta++;
}
sum = num - 1; delta = 1;
while (sum != 0) {
if (r+sum < n && c+delta > -1) {
arr[r + sum][c + delta] = (char) (num + '0');
}
sum--;
delta++;
}
}
num++;
}
I could not figure out any other way to take care of the diagonal numbers other than using four different while-loops. I would appreciate any kind of feedback. Thanks in advance!
You can just loop over the array once, and set the values based on the relative distance of the current location (i, j) to the fixed coordinate (x, j).
Your code could look like this:
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
// variables
int n = 8;
int x = 4 - 1; // coordinates are one-based
int y = 5 - 1; // coordinates are one-based
int r = 3;
char[][] array = new char[n][n];
// logic
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int dist = Math.abs(x - i) + Math.abs(y - j); // calculate distance
if(dist == 0) { // at x,y
array[i][j] = 'x';
} else if (dist <= r) { // distance to x,y is within range
array[i][j] = (char) (dist + '0');
} else { // distance to x,y is outside of range
array[i][j] = '0';
}
}
}
// dump output
System.out.println(Arrays.deepToString(array)
.replace("], ", "]\n")
.replace("[", "")
.replace("]", "")
.replace(", ", " "));
}
}
Which yields the following output:
0 0 0 0 3 0 0 0
0 0 0 3 2 3 0 0
0 0 3 2 1 2 3 0
0 3 2 1 x 1 2 3
0 0 3 2 1 2 3 0
0 0 0 3 2 3 0 0
0 0 0 0 3 0 0 0
0 0 0 0 0 0 0 0
If you want to be even more concise, you can replace the branched if… else if… else statement with ternary operators:
array[i][j] = dist == 0 ? 'x' : dist <= r ? (char) (dist + '0') : '0';
Here's a fairly compact method. On each iteration i we fill a single-character wide i+1 by i+1 diamond-shaped ring, centered on (row, col), with value i. To avoid filling the interior of the diamond we check that the manhattan distance to (row, col) is equal to i - this is only true for cells on the boundary of the diamond.
static char[][] buildDiamond(int n, int row, int col, int range)
{
char[][] arr = new char[n][n];
for(char[] a : arr) Arrays.fill(a, '0');
arr[row][col] = 'x';
for(int i=1; i<=range; i++)
for(int j=0; j<=i; j++)
for(int k=0; k<=i; k++)
if(Math.abs(k-j) + Math.abs(k+j-i) == i)
arr[row+k-j][col+k+j-i] += i;
return arr;
}
Test:
public static void main(String[] args)
{
for(char[] a : buildDiamond(7, 3, 3, 3))
System.out.println(new String(a).replaceAll(".", "$0 "));
}
Output:
0 0 0 3 0 0 0
0 0 3 2 3 0 0
0 3 2 1 2 3 0
3 2 1 x 1 2 3
0 3 2 1 2 3 0
0 0 3 2 3 0 0
0 0 0 3 0 0 0
You can try using floodfill, although depending on your level it might be a bit far.
https://en.wikipedia.org/wiki/Flood_fill
EDIT: Robby Cornelissen's code looks much cleaner and simpler than mine so you should probably check out his. However, floodfill is a pretty important concept for later on so might as well check it out.
The article is pretty long, but the GIF in the article is the most important part.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class test {
public static void main(String[] args) throws IOException {
//Get inputs (I used BufferedReader, Scanner works fine as well)
//My inputs are formatted as 'N X Y R' (ex. '8 4 5 3')
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
int N = Integer.parseInt(st.nextToken());
int R = Integer.parseInt(st.nextToken()) - 1;
int C = Integer.parseInt(st.nextToken()) - 1;
int range = Integer.parseInt(st.nextToken());
char[][] arr = new char[N][N];
//Make everything in array '0'
for (int i = 0; i < N; i++) {
Arrays.fill(arr[i], '0');
}
//Floodfill using BFS
//FYI: this BFS is iterative, not recursive
Queue<int[]> q = new LinkedList<>();
q.add(new int[]{0, R, C});
while (!q.isEmpty()) {
int[] current = q.remove();
if (arr[current[1]][current[2]] == '0' && current[0] <= range) {
arr[current[1]][current[2]] = (current[0]+"").charAt(0);
if(current[1]+1 < N) q.add(new int[]{current[0]+1, current[1]+1, current[2]});
if(current[1]-1>= 0) q.add(new int[]{current[0]+1, current[1]-1, current[2]});
if(current[2]+1 < N) q.add(new int[]{current[0]+1, current[1], current[2]+1});
if(current[2]-1>= 0) q.add(new int[]{current[0]+1, current[1], current[2]-1});
}
}
arr[R][C] = 'x';
//Print out the final grid
for (int i = 0; i < N; i++) {
for (int j = 0; j< N; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}

DFS and BFS with adjacency matrix counted in Java

Currently trying to build a program that can implement both DFS and BFS in Java by taking in an adjacency matrix from a file and printing out the following info: order that vertices are first encountered, order that vertices become dead ends, number of components, and the tree edges.
Here is my code:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class ProjectDriver {
public static int count;
public static void main(String[] args) throws FileNotFoundException {
ArrayList<Integer> dfsDeadEnd = new ArrayList<Integer>();
ArrayList<Integer> dfsVertices = new ArrayList<Integer>();
ArrayList<Integer> bfsVertices = new ArrayList<Integer>();
int dfsComponents = 0;
int bfsComponents = 0;
Scanner scanner = new Scanner(new File("sample1.txt"));
int n = 8;
int[][] edges = new int[n][n];
boolean[] visited = new boolean[n];
count = 0;
for(int i=0; i < n; i++) {
for (int j=0; j < n; j++) {
edges[i][j] = scanner.nextInt();
}
}
for(int i = 0; i < n; i++){
visited[i] = false;
}
int[][] BFStreeEdgeGraph = new int[n][n];
int[][] DFStreeEdgeGraph = new int[n][n];
int[][] crossGraph = new int[n][n];
for(int i = 0; i <= n-1; i++){
for(int j = 0; j <= n-1; j++){
DFStreeEdgeGraph[i][j] = 0;
BFStreeEdgeGraph[i][j] = 0;
crossGraph[i][j] = 0;
}
}
for(int i = 0; i <= n-1; i++){
if(visited[i] == false){
dfs(edges,i,visited, dfsVertices, dfsDeadEnd, DFStreeEdgeGraph);
dfsDeadEnd.add(i);
dfsComponents++;
}
}
for(int i = 0; i <= n-1; i++) {
if(visited[i] == false) {
bfs(edges, i, visited, bfsVertices, BFStreeEdgeGraph);
bfsComponents++;
}
}
System.out.println();
System.out.println("DFS: Number of Connected Components: " + dfsComponents);
System.out.print("DFS: Order of First Encountered: ");
for(int i : dfsVertices){
System.out.print((i+1) + " ");
}
System.out.println();
System.out.print("DFS: Order of First Dead-Ends: ");
for(int i : dfsDeadEnd){
System.out.print((i+1) + " ");
}
System.out.println();
System.out.println();
System.out.println("Tree edges:");
displayGraph(DFStreeEdgeGraph, n);
System.out.println();
System.out.println();
System.out.println("BFS: Number of Connected Components: " + bfsComponents);
System.out.print("BFS: Order of First encountered: ");
for(int i : bfsVertices){
System.out.print((i+1) + " ");
}
System.out.println();
System.out.println();
}
public static void dfs(int[][] edges, int vertex, boolean[] visited, ArrayList<Integer> dfsVertices, ArrayList<Integer> dfsDeadEnd, int[][] DFStreeEdgeGraph) {
visited[vertex] = true;
dfsVertices.add(count, vertex);
count = count + 1;
for(int w = 0; w <= edges.length-1; w++) {
if(edges[vertex][w] == 1 && !visited[w]) {
DFStreeEdgeGraph[vertex][w] = 1;
dfs(edges, w, visited, dfsVertices, dfsDeadEnd, DFStreeEdgeGraph);
dfsDeadEnd.add(w);
}
}
}
public static void bfs(int[][] edges, int vertex, boolean[] visited, ArrayList<Integer> bfsVertices, int[][] BFStreeEdgeGraph) {
bfsVertices.add(count, vertex);
count = count + 1;
for(int w = 0; w < edges.length; w++) {
if(edges[vertex][w] != 0 && !visited[w]) {
visited[vertex] = true;
}
}
for(int w = bfsVertices.indexOf(vertex) + 1; w < bfsVertices.size(); w++) {
int value = bfsVertices.get(w);
bfs(edges, value, visited, bfsVertices, BFStreeEdgeGraph);
}
}
public static void displayGraph(int[][] graph, int n) {
for(int i = 0; i <= n-1; ++i){
System.out.print(" ");
for(int j = 0; j <= n-1; ++j){
System.out.print(graph[i][j] + " ");
}
System.out.println();
}
}
}
And here is the output from running my code:
Input graph:
0 1 0 0 1 1 0 0
1 0 0 0 0 1 1 0
0 0 0 1 0 0 1 0
0 0 1 0 0 0 0 1
1 0 0 0 0 1 0 0
1 1 0 0 1 0 0 0
0 1 1 0 0 0 0 1
0 0 0 1 0 0 1 0
DFS: Number of Connected Components: 1
DFS: Order of First Encountered: 1 2 6 5 7 3 4 8
DFS: Order of First Dead-Ends: 5 6 8 4 3 7 2 1
Tree edges:
0 1 0 0 0 0 0 0
0 0 0 0 0 1 1 0
0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
BFS: Number of Connected Components: 0
BFS: Order of First encountered:
And here are my issues. For the DFS, my order of first encountered should be 1 2 6 7 4 3 5 8, but this is not what I'm getting. Additionally, my order of dead ends should be 8 7 5 4 1 2 6 3, but this is also off. My tree edges managed to come out correct.
For the BFS, I can't get anything to print, and debugging my DFS and BFS methods hasn't given me the answer yet. I'd be very grateful from some help.

Conway's Game of Life New Values

The question revolves around Conway's Game of Life and how to implement all the rules at the same time for the new generations. The game follows three rules for new generations, which are: a dead cell with exactly three live neighbors becomes live, a live cell with exactly one live neighbor becomes dead, and a live cell with more than three live neighbors becomes dead. The original generation is random. I think my problem, which is that my new generations are implementing the rules one at a time instead of all at once, is in this method:
public static int[][] nextgeneration(int[][] lastgen){
int[][] nextgen = new int[lastgen.length][lastgen[0].length];
for(int i = 0; i < lastgen.length; i++){
for(int j = 0; j < lastgen[i].length; j++){
if(aliveneighbors(lastgen, i, j) == 3){
nextgen[i][j] = 1;
}
else if(aliveneighbors(lastgen, i, j) == 1){
nextgen[i][j] = 0;
}
else if(aliveneighbors(lastgen, i, j) > 3){
nextgen[i][j] = 0;
}
else nextgen[i][j] = lastgen[i][j];
}
}
return nextgen;
Here's my full code just in case the problem was not in that method:
import java.util.Random;
public class Life {
public static int[][] origin(int a, int b) {
int[][] randomMatrix = new int [a][b];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
Random random = new Random();
int abc = random.nextInt(2);
randomMatrix[i][j] = abc;
}
}
return randomMatrix;
}
public static void print(int[][] a) {
for(int i = 0; i < a.length; i++){
for(int j = 0; j < a.length; j++){
System.out.print(a[i][j] + " ");
}
System.out.println();
}
}
public static void show(int[][] b) {
int N = b.length;
StdDraw.setXscale(0, N-1);
StdDraw.setYscale(0, N-1);
for(int i = 0; i < b.length; i++){
for(int j = 0; j < b.length; j++){
if(b[i][j] == 1){
StdDraw.setPenColor(StdDraw.RED);
StdDraw.filledSquare(j, N-i-1, .5);
}
else if(b[i][j] == 0){
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.filledSquare((double)j, (double)-i, .5);
}
}
}
}
public static int[][] nextgeneration(int[][] lastgen){
int[][] nextgen = new int[lastgen.length][lastgen[0].length];
for(int i = 0; i < lastgen.length; i++){
for(int j = 0; j < lastgen[i].length; j++){
if(aliveneighbors(lastgen, i, j) == 3){
nextgen[i][j] = 1;
}
else if(aliveneighbors(lastgen, i, j) == 1){
nextgen[i][j] = 0;
}
else if(aliveneighbors(lastgen, i, j) > 3){
nextgen[i][j] = 0;
}
else nextgen[i][j] = lastgen[i][j];
}
}
return nextgen;
}
public static int aliveneighbors(int[][] board, int x, int y){
int count = 0;
int up;
int down;
int left;
int right;
{
if(x > 0)
up = x - 1;
else
up = board.length - 1;
if(x < (board.length - 1))
down = x + 1;
else
down = 0;
if(y > 0)
left = y - 1;
else
left = board[x].length - 1;
if(y < (board[x].length - 1))
right = y + 1;
else
right = 0;
//Count the live neighbors
if(board[up][left] == 1)
count++;
if(board[up][y] == 1)
count++;
if(board[up][right] == 1)
count++;
if(board[x][left] == 1)
count++;
if(board[x][right] == 1)
count++;
if(board[down][left] == 1)
count++;
if(board[down][y] == 1)
count++;
if(board[down][right] == 1)
count++;
return count;
}
}
public static void main(String[] args) {
int[][] b = origin(5, 5);
int gens = 5;
for (int i = 0; i < gens; i++) {
System.out.println();
int nextboard[][] = nextgeneration(b);
b = nextboard; //I feel like this could be a problem as well
System.out.println("Generation " + i + ":");
print(nextgeneration(b));
show(nextgeneration(b)); //This line of code seems useless
//print(b); This one also seems useless and makes output confusing
show(b);
}
}
}
Here is what my output is:
Generation 0:
0 1 1 0 0
0 1 1 0 0
0 0 0 1 1
1 1 0 1 1
1 0 0 0 0
Generation 1:
1 0 1 0 0
1 1 0 0 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
Generation 2:
1 0 1 0 1
1 1 0 0 0
1 0 0 0 0
0 0 1 1 0
0 0 0 1 1
Generation 3:
0 0 1 0 0
0 0 0 0 0
1 0 1 0 1
0 0 1 1 0
1 1 0 0 0
Generation 4:
0 1 0 0 0
0 1 0 1 0
0 1 1 0 1
0 0 1 1 0
0 1 0 1 0
I expect something like this:
Generation 0:
0 1 1 0 0
0 1 1 0 0
0 0 0 1 1
1 1 0 1 1
1 0 0 0 0
Generation 1:
0 1 1 0 0
0 1 0 0 0
1 0 0 0 1
1 1 1 1 1
1 1 0 0 0
Generation 2:
0 1 1 0 0
1 1 1 0 0
1 0 0 0 1
0 0 1 1 1
1 0 0 1 0
Also on my animation of the game the alive cells stay alive in the animation, which should not be happening. That's not my main problem, but if you know how to fix that it would also be helpful.
Your output looks fine to me. Pay attention, that you actually do "wrap-around" of the borders, so this
Generation 0:
0 1 1 0 0
has this as a upper border:
1 0 0 0 0
and a left border:
0
0
1
1
0
For calculations it looks like:
0 1 0 0 0 0
0 0 1 1 0 0
0 0 1 1 0 0
So this output:
Generation 1:
1 0 1 0 0
1 1 0 0 0
Is correct for the wrap-around.
From the expected result, however, it looks you want to treat it as a actual border. I mean:
010
000
with x=1, y=0, has only 5 neighbours.
In that case you need something like this:
public static int aliveneighbors(int[][] board, int x, int y){
int width = board.length;
int height = board[0].length;
int count = 0;
boolean isNotLower = (y-1) >= 0;
boolean isNotUpper = (y+1) < height;
if (x-1 >= 0) {
if( isNotLower && (board[x-1][y-1] == 1) )
count++;
if(board[x-1][y] == 1)
count++;
if(isNotUpper && (board[x-1][y+1] == 1) )
count++;
}
if (x+1 < width) {
if( isNotLower && (board[x+1][y-1] == 1) )
count++;
if(board[x+1][y] == 1)
count++;
if( isNotUpper && (board[x+1][y+1] == 1) )
count++;
}
if( isNotUpper && (board[x][y+1] == 1) )
count++;
if(isNotLower && (board[x][y-1] == 1) )
count++;
return count;
}

2^N Combinaisons with Integers (Kernel), how to generate them?

(Merry Christmas btw ^^)
Here is my problem (in JAVA) but it's definitely an algorithmic problem and I don't know how to solve it :/
So here it is, with an example (just for information, all my calculs are in Binary, so 1+1 = 0)
let's name variables:
N : the number of elements in kernel.
M : the length of an element in the kernel.
int[][] Kernel:
....
i : 0 1 1 1 0 1 0 1 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 0 (length = M)
i+1 : 1 0 1 0 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 1 1 0 1 0 1 (length = M)
....
N : ....
My goal with theses things, is to generate all the possible combinaison (so 2^N elements)
and I want to generate them.
By generate I mean exactly this :
Result[0] = 0 0 0 0 0 0 0 0 0 0 0 0 0
Result[1] = Kernel[0]
Result[2] = Kernel[1]
....
Result[i] = Kernel[i-1]
Result[N-1] = Kernel[N-2]
Result[N] = Kernel[0] + Kernel[1]
Result[N+1] = Kernel[0] + Kernel[2]
Result[N+i] = Kernel[0] + Kernel[i]
Result[2N-1] = Kernel[0] + Kernel[N-1]
....
Result[I] = Kernel[0] + Kernel[1] + Kernel[2]
Result[I+1] = Kernel[0] + Kernel[1] + Kernel[i]
Result[I+J] = Kernel[0] + Kernel[1] + Kernel[N-1]
....
Result[2^N+1] = Kernel[0] + Kernel[1] + ... + Kernel[i] + ... + Kernel[N-1]
Here is what I already success to do, but it's not complete and I don't know how to generalize the calcul in order to work with any N...
public static int[][] combinaisons(int[][] kernel) {
/* if the kernel is empty, there is no possible combinaison */
if(kernel.length == 0) return kernel;
/* We allocate the good number of space... */
int[][] result = new int[(int) (Math.pow(2, noyau.length)+1)][];
/* Every element in result has the same length as in kernel's elements. */
for(int i = 0; i < resultat.length; i++) {
result[i] = new int[kernel[0].length];
}
/* The first element of result has to be only 0 0 0 0 0 0 0 */
for(int j = 0; j < kernel[0].length; j++) {
result[0][j] = 0;
}
/* We rewrite the element of kernel because they are a part of the solution... */
for(int i = 0; i < kernel.length; i++) {
for(int j = 0; j < kernel[i].length; j++) {
result[i+1][j] = kernel[i][j];
}
}
/*
I managed to do it when it's the sum of only 2 elements,
but it has to be with 3, 4 ... N-1 :/
*/
for(int i = 0; i < kernel.length; i++) {
for(int j = 0; j < kernel[i].length; j++) {
for(int k = i+1; k < kernel.length; k++) {
result[k*kernel.length+i][j] = (kernel[i][j]+kernel[k][j])%2;
}
}
}
return result;
}
Edit:
About an example, let's give this:
N = 2
M = 4
Kernel:
0 1 1 0
1 0 0 1
In result I want:
0 0 0 0
0 1 1 0
1 0 0 1
1 1 1 1 (the sum of the 2 elements in Kernel)
So this is a simple example (quite particularly values, if you want bigger, just ask :) )
Even if the array at the end seems to be VERY HUGE :) that's exactly what I want to generate (don't care about memory, it will for sure be okay)
I am going to use boolean[][] instead of int[][]. 0 means false, 1 means true.
public static boolean[][] combinations(boolean kernel[][]) {
int n = kernel.length;
int m = kernel[0].length;
int p = 1 << n;
boolean[][] temp = new boolean[p][m];
for (int i = 0; i < p; i++)
for (int j = 0; j < n; j++)
if (((1 << j) & i) != 0)
for (int k = 0; k < m; k++)
temp[i][k] ^= kernel[j][k];
return temp;
}

Categories

Resources