I need to check all possible paths that is reachable from one certain cell in a 2d array. For example;
int [][] grid = {{2, 0, 0, 1, 1, 2},
{1, 0, 2, 0, 0, 1},
{1, 0, 2, 0, 4, 2},
{8, 3, 4, 0, 1, 2},
{1, 2, 5, 0, 3, 3},
{5, 1, 1, 2, 1, 0}};`
and I want to check all cells that is reachable from cell(2)(1) (it is just an example location). First some number will be placed here if this location is zero. For example, 1 is placed at that location.
Then I need to start merging all 1’s which are reachable from cell (2,1).Then cell(2)(1) location must be replaced with the 2 if the cells that create this path includes at least two 1 since 1+1 = 2.
After that, the cells which are used during merging process must be assigned to zero.
But if there is still possible merging for cell(2)(1) they should be merged too.
I try to use recursive function but it did not work as I want.
I could not figure out how to prevent merging if there are less than 3 neighbor cells which includes same value and how to merge until no possible merging left. Method should continue merging until there are no possible merge left, but my code merge for once. I have just started to learn java sorry for mistakes already now.
So...
I am not sure if I got everything right because some things are misleading.
cell(2)(2) has the initial content: 2
I think your chosen cell is (1)(2). //note: indices in java start with 0
So your idea is a little bit more complex and should not be solved with only one method.
I've written some code:
private static int[][] directions = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
public static void step(int[][] array, int x, int y) {
if(array[x][y] == 0){
array[x][y] = 1;
}else{
return;
}
int number = 1;
while(true){
printGrid(array);
int amount = process(array, x, y);
if(amount == 1)break;
number ++;
array[x][y] = number;
}
}
public static int process(int[][] array,int x, int y){
int number = array[x][y];
if(number == 0) return 0;
int total = 1;
array[x][y] = 0;
for(int[] dire:directions){
if(x + dire[0] >= 0 && x + dire[0] < array.length && y + dire[1] >= 0 && y + dire[1] < array[0].length){
if(array[x + dire[0]][y+dire[1]] == number){
total += process(array, x + dire[0], y+dire[1]);
}
}
}
return total;
}
public static void printGrid(int[][] grid) {
for(int i = 0; i < grid.length; i++){
String s = "";
for(int n = 0; n< grid[0].length; n++){
s += grid[i][n]+", ";
}
System.out.println(s);
}
System.out.println("");
}
public static void main(String[] args){
int [][] grid =
{{2, 0, 0, 1, 1, 2},
{1, 0, 2, 0, 0, 1},
{1, 0, 2, 0, 4, 2},
{8, 3, 4, 0, 1, 2},
{1, 2, 5, 0, 3, 3},
{5, 1, 1, 2, 1, 0}};
Main.step(grid, 2,1);
printGrid(grid);
}
I modified it like this;
public static void main(String []args){
System.out.println("Welcome to the game Merge Numbers. Your grid as follows:");
int[][] newGrid = {{2, 0, 1, 1, 0, 8},
{2, 1, 0, 2, 4, 0},
{1, 2, 1, 2, 1, 3},
{2, 3, 2,0, 1, 0},
{0, 0, 5, 8, 7, 2},
{2, 0, 1, 1, 0, 0}};
for(int i = 0 ; i < newGrid.length ; i++){
for (int j = 0; j < newGrid[i].length; j++) {
System.out.print(newGrid[i][j] + " ");
}
System.out.println();
}
try (Scanner keyboard = new Scanner(System.in)){
System.out.print("Please enter your target's row index:");
int newRow = keyboard.nextInt();
System.out.print("Please enter your target's column index:");
int newColumn = keyboard.nextInt();
System.out.print("Please enter the number that you want to add to location " + newRow + " " + newColumn);
int newNextNumber = keyboard.nextInt();
step(newGrid, newRow, newColumn, newNextNumber);
for(int i = 0 ; i < newGrid.length ; i++){
for (int j = 0; j < newGrid[i].length; j++) {
System.out.print(newGrid[i][j] + " ");
}
System.out.println();
}}
}
public static void step(int[][] grid, int row, int column, int nextNumber ) {
if(grid[row][column] == 0){
grid[row][column] = nextNumber;
}else{
return;
}
int number = nextNumber;
while(true){
int amount = process(grid, row, column);
if(amount == 1)break;
number ++;
grid[row][column] = number;
}
}
public static int process(int[][] grid,int row, int column){
int number = grid[row][column];
if(number == 0) return 0;
int total = 1;
grid[row][column] = 0;
for(int[] dire:directions){
if(row + dire[0] >= 0 && row + dire[0] < grid.length && column + dire[1] >= 0 && column + dire[1] < grid[0].length){
if(grid[row + dire[0]][column+dire[1]] == number){
total += process(grid, row + dire[0], column+dire[1]);
}
}
}
return total;
}
}
But when I run it all the points include the target location becomes zero. Output is like;
Welcome to the game Merge Numbers. Your grid as follows:
2 0 1 1 0 8
2 1 0 2 4 0
1 2 1 2 1 3
2 3 2 0 1 0
0 0 5 8 7 2
2 0 1 1 0 0
Please enter your target's row index:3
Please enter your target's column index:3
Please enter the number that you want to add to location 3 3: 1
2 0 1 1 0 8
2 1 0 0 4 0
1 2 1 0 0 3
2 3 0 0 0 0
0 0 5 8 7 2
2 0 1 1 0 0
I mean if you look at the first grid in the output, cell(3)(3) is zero. When 1 is placed here, the 1's that are reachable from this cell(3)(3) merged. Then cell(3)(3) includes 2. After that same procedure follows. But when all possible merges done, all cells that has been used during the process include center became 0. Center should be increase by one after each merging. I think, I use the fourth parameter which is nextNumber incorrectly. Should function process also include that parameter or not? Sorry to disturb you so much :)
here is how you can find neighbors of a cell...
int x[] = {-1, -1, -1, 0, 0, +1, +1, +1};
int y[] = {-1, 0, +1, -1, +1, -1, 0, +1};
// looping through the neghibours...
for(int i=0; i<8; i++) {
if( p+x[i] < n && q+y[i] < m && a[p + x[i]][q + y[i]] == a[p][q]) {
// neighbour
}
}
Here is the recursive implementation of your problem, n & m is the size of grid a and p & q is the index of the cell you want to perform merge...
public static void merge(int a[][], int n, int m, int p, int q) {
int x[] = {-1, -1, -1, 0, 0, +1, +1, +1};
int y[] = {-1, 0, +1, -1, +1, -1, 0, +1};
int c = 0;
// looping through the neghibours...
for(int i=0; i<8; i++) {
if( p+x[i] < n && q+y[i] < m && a[p + x[i]][q + y[i]] == a[p][q]) {
c++;
}
}
if(c > 3) { // merging only if neghibours > 3
for(int i=0; i<8; i++) {
if( p+x[i] < n && q+y[i] < m && a[p + x[i]][q + y[i]] == a[p][q]) {
a[p + x[i]][q + y[i]] = 0;
}
}
a[p][q] += 1;
merge(a, n, m, p, q); // recurcively merging if possible...
}
}
Related
I have a 2D Array:
{0, 0, 1, 1, 1},
{0, 0, 1, 1, 1},
{0, 0, 1, 1, 1},
{0, 1, 0, 0, 1}
and I am trying to see which row has the closest 1 to the left, in this case it is index 3. So we have to return 3 to console, but I don't know how to go about comparing the values, etc.
This is what I have tried so far:
int array[][] = {
{0, 0, 1, 1, 1},
{0, 0, 1, 1, 1},
{0, 0, 1, 1, 1},
{0, 1, 0, 0, 1}
};
int count = 0;
Map<Integer, Integer> countMap = new HashMap<>();
for(int i = 0; i < array.length; i++){
for(int j = 0; j < array[i].length; j++){
if(array[i][j] != 1){
count++;
}else{
System.out.println("index of i: " + i + ", index of j:" + j + ", count: " + count);
countMap.put(j, count);
count = 0;
break;
}
}
}
System.out.println();
You can try to iterate in a column wise manner and return result as soon as you encounter the first '1'. This way you don't need to spend extra computation iterating through the whole 2D matrix.
public class ClosestOne {
public static int closestOne(int[][] a) {
for(int i = 0; i < a[0].length; i++) {
for(int j = 0; j < a.length; j++) {
if(a[j][i] == 1) {
return j;
}
}
}
return -1;
}
public static void main(String[] args) {
int array[][] = {
{0, 0, 1, 1, 1},
{0, 0, 1, 1, 1},
{0, 0, 1, 1, 1},
{0, 1, 0, 0, 1}
};
int closestRow = closestOne(array);
if(closestRow == -1) {
System.out.println("'1' is not present in matrix!");
} else {
System.out.println("Closest '1' is in row: " + closestRow );
}
}
}
Using a HashMap is completely over-engineered here. Theoretically you do not need any kind of data structure since you calculate the values row-by-row anyways, but since you were using one, I thought I would use one, too.
Use a simple array instead of the Map, with the length of the original array (i.e. the rows). Fill that array with a number that is higher than any result can be, to be safe I used Integer.MAX_VALUE.
int[] firstIndex = new int[array.length];
//for all i in length of array:
firstIndex[i] = Integer.MAX_VALUE;
No iterate though your your 2d array like you are and overwrite the firstIndex if you find something that is better than the current value.
//for every row
//for ever column (col)
if (array[row][col] == 1 && col < firstIndex[row]) {
firstIndex[row] = col;
}
Then in the end look for the minimum value in that array.
int min = firstIndex[0];
for (int row = 1; row < firstIndex.length; row++) {
min = Integer.min(min, firstIndex[row]);
}
System.out.println(min);
It looks like you have already worked out the count to the first 1 on each row, you just need to decide which is the lowest after completing your loop. You don't need a map to do that, just check if the current row is better than the "best so far" and if it is then update the best.
There is actually no need for a count variable since j is the same thing, and i is the row.
int best = -1; // Initialize to -1 which is an invalid index
int bestCount = Integer.MAX_VALUE; // Initialize to a very bad best count.
for(int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] == 1 && j < bestCount) {
best = i; // the row
bestCount = j; // the '1'
break;
}
}
}
System.out.println("Closest 1 to left in row " + best);
I need to count how many rows does the user inputs that are only 0, something like:
Test 1
0 0 0
1 2 3
2 2 1
Test 2
1 2 3
0 0 0
0 0 0
Rows with only 0 values: 3
This is the code that reads the matrices:
final int rows = 3, cols = 3;
Scanner input = new Scanner(System.in);
System.out.println("Number of tests");
int n = input.nextInt();
int test[][][] = new int[n][rows][cols];
for (int i = 0; i < n; i++) {
System.out.println("Test " + (i + 1));
for (int j = 0; j < rows; j++) {
for (int k = 0; k < cols; k++) {
test[i][j][k] = input.nextInt();
}
}
}
You can get the number of zero rows in a 3D matrix using Streams as follows:
public static void main(String[] args) {
int[][][] test = {
{{0, 0, 0}, {1, 2, 3}, {2, 2, 1}},
{{1, 2, 3}, {0, 0, 0}, {0, 0, 0}}};
System.out.println(zeroRowsCount(test)); // 3
}
public static long zeroRowsCount(int[][][] arr3d) {
return Arrays.stream(arr3d)
// the number of zero rows in each 2D array
.mapToLong(arr2d -> zeroRowsCount(arr2d))
// total number of zero rows
.sum();
}
public static long zeroRowsCount(int[][] arr2d) {
return Arrays.stream(arr2d)
// filter those rows that consist of zeros
.filter(row -> Arrays.stream(row)
// all elements are zeros
.allMatch(i -> i == 0))
// the number of zero rows
.count();
}
I have to find the distances in a graph through the multiplication of a 2D array, and I am trying to multiply the array of the graph, it works but the output is not correct.
And I don't know where the problem is!
public class Graph {
private int[][] AdjacencyMatrix = {
{0, 1, 0, 1, 0},
{1, 0, 1, 0, 1},
{0, 1, 0, 1, 0},
{1, 0, 1, 0, 0},
{0, 1, 0, 0, 0}};
int size = AdjacencyMatrix.length;
private int[][] distanceMatix = new int[size][size];
public void multiply() {
int sum = 0;
//für alle Zeilen in this matrix
for (int row = 0; row < size; row++) {
//für alle Spalten in other matrix
for (int col = 0; col < size; col++) {
//this matrix -> für alle Zellen in der Zeile
//other matrix -> für alle Zellen in der Spalte
for (int index = 0; index < size; index++) {
if (row == col) {
distanceMatix[row][col] = 0;
} else {
distanceMatix[row][col] +=
AdjacencyMatrix[row][index] *
AdjacencyMatrix[index][col];
}
}
}
}
System.out.println("\n-------- Print DistanceMatrix --------\n");
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.print(distanceMatix[i][j] + " ");
}
System.out.println();
}
}
}
My Output:
0 0 2 0 1
0 0 0 2 0
2 0 0 0 1
0 2 0 0 0
1 0 1 0 0
The correct ouput is this:
0 1 2 1 2
1 0 1 2 1
2 1 0 1 2
1 2 1 0 3
2 1 2 3 0
Your inner loop should look like this. Primitive arrays are intitialized to 0's upon creation and you don't want to skip an iteration when row == col.
for (int index = 0; index < size; index++) {
distanceMatix[row][col] += AdjacencyMatrix[row][index] *
AdjacencyMatrix[index][col];
}
I used
1 2
3 4
And multiplied by hand and got
7 10
15 22
Which matches your program with above changes.
With regard to your expected answer, either it is wrong your input matrix may be wrong. You can verify your answers here
You can use a generic matrix multiplication approach so you don't get confused:
int size = 5;
int[][] matrix = {
{0, 1, 0, 1, 0},
{1, 0, 1, 0, 1},
{0, 1, 0, 1, 0},
{1, 0, 1, 0, 0},
{0, 1, 0, 0, 0}};
int[][] result = new int[size][size];
for (int row = 0; row < size; row++)
for (int col = 0; col < size; col++)
for (int index = 0; index < size; index++)
result[row][col] += matrix[row][index] * matrix[index][col];
// output
for (int[] res : result) System.out.println(Arrays.toString(res));
//[2, 0, 2, 0, 1]
//[0, 3, 0, 2, 0]
//[2, 0, 2, 0, 1]
//[0, 2, 0, 2, 0]
//[1, 0, 1, 0, 1]
See also: An efficient way to multiply two object matrixes
I have a task.I need to find the biggest area with equal numbers(e.g. neighbours by row or column). The program that i made works fine,but the problem is that if i have the following matrix:
{ 1, 3, 2, 2, 2, 4 }
{ 3, 1, 3, 2, 4, 4 }
{ 4, 3, 1, 2, 3, 3 }
{ 4, 3, 1, 3, 3, 1 }
{ 4, 3, 3, 3, 1, 1 }
The program will print 10.Okay maybe some of you may say that it's because i add 1 to the final result,yeah that's true but if i don't add 1 ,and if the number at position [1][1] was 3 instead of 1 ,i would get 12 witch is wrong,so that`s why i add 1.So my question is do you have any suggestions about optimazing the algorithm..if yes,i would be very thankful to hear them :)..
Here is my code:
protected int counter = 0;
protected int max = 1;
protected enum eState {
Vi,
InPr,
Unvi
};
public void recNodeMatrix(int i, int j, eState st[][],int [][]matr,int n,int k) {
st[i][j] = eState.InPr;
for (int r = 0; r < n; r++) {
for (int c = 0; c < k; c++) {
if ((matr[i][j] == matr[r][c])
&& ((((i+j) - (r + c)) == 1) || (((i+j) - (r + c)) == -1))
&& ((st[r][c] == eState.Unvi))) {
counter++;
recNodeMatrix(r, c, st,matr,n,k);
}
}
}
st[i][j] = eState.Vi;
}
public void Zad17() {
int n=5,k=6;
eState st[][] = new eState[n][k];
int[][] matr = new int[][] {
{ 1, 3, 2, 2, 2, 4 },
{ 3, 1, 3, 2, 4, 4 },
{ 4, 3, 1, 2, 3, 3 },
{ 4, 3, 1, 3, 3, 1 },
{ 4, 3, 3, 3, 1, 1 } };
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
st[i][j] = eState.Unvi;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
if(st[i][j] == eState.Unvi) {
recNodeMatrix(i, j, st,matr,n,k);
if(max<counter)
max=counter;
counter =0;
}
}
}
System.out.print(max+1);
}
Probably the best way to solve this problem is with a union-find data structure: https://en.wikipedia.org/wiki/Disjoint-set_data_structure
Initially, each cell is its own set, and then you merge the sets for every pair of adjacent cells that have equal numbers in them.
When you're done, the answer is the size of the biggest set. Since you have to keep track of the set sizes anyway, use union-by-size instead of union-by-rank.
Applying a bit of cleverness, you can implement the union-find with just an array of N*K integers -- one for each cell. Each integer is either the index of the parent set or -size for roots.
This solves the problem in about linear time, and will probably be faster in practice than flood-fill solutions using a similar amount of memory.
So I have a matrix of N×M. At a given position I have a value which represents a color. If there is nothing at that point the value is -1. What I need to do is after I add a new point, to check all his neighbours with the same color value and if there are more than 2, set them all to -1.
If what I said doesn't make sense what I'm trying to do is an algorithm which I use to destroy all the same color bubbles from my screen, where the bubbles are memorized in a matrix where -1 means no bubble and {0,1,2,...} represent that there is a bubble with a specific color.
Also, if you have any suggestions I'd be grateful. Thanks.
This is what I tried and failed:
public class Testing {
static private int[][] gameMatrix=
{{3, 3, 4, 1, 1, 2, 2, 2, 0, 0},
{1, 4, 1, 4, 2, 2, 1, 3, 0, 0},
{2, 2, 4, 4, 3, 1, 2, 4, 0, 0},
{0, 4, 2, 3, 4, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
static int Rows=6;
static int Cols=10;
static int count;
static boolean[][] visited=new boolean[15][15];
static int NOCOLOR = -1;
static int color = 1;
public static void dfs(int r, int c, int color, boolean set)
{
for(int dr = -1; dr <= 1; dr++)
for(int dc = -1; dc <= 1; dc++)
if(!(dr == 0 && dc == 0) && ok(r+dr, c+dc))
{
int nr = r+dr;
int nc = c+dc;
// if it is the same color and we haven't visited this location before
if(gameMatrix[nr][nc] == color && !visited[nr][nc])
{
visited[nr][nc] = true;
count++;
dfs(nr, nc, color, set);
if(set)
{
gameMatrix[nr][nc] = NOCOLOR;
}
}
}
}
static boolean ok(int r, int c)
{
return r >= 0 && r < Rows && c >= 0 && c < Cols;
}
static void showMatrix(){
for(int i = 0; i < gameMatrix.length; i++) {
System.out.print("[");
for(int j = 0; j < gameMatrix[0].length; j++) {
System.out.print(" " + gameMatrix[i][j]);
}
System.out.println(" ]");
}
System.out.println();
}
static void putValue(int value,int row,int col){
gameMatrix[row][col]=value;
}
public static void main(String[] args){
System.out.println("Initial Matrix:");
putValue(1, 4, 1);
putValue(1, 5, 1);
putValue(1, 4, 2);
showMatrix();
for(int n = 0; n < Rows; n++)
for(int m = 0; m < Cols; m++)
visited[n][m] = false;
//reset count
count = 0;
dfs(5,1,color,false);
//if there are more than 2 set the color to NOCOLOR
for(int n = 0; n < Rows; n++)
for(int m = 0; m < Cols; m++)
visited[n][m] = false;
if(count > 2)
{
dfs(5,1,color,true);
}
System.out.println("Matrix after dfs:");
showMatrix();
}
}
One issue you are encountering is that you do not check the upper row and leftest col:
static boolean ok(int r, int c)
{
return r > 0 && r < Rows && c > 0 && c < Cols;
}
you should check for r >= 0, c>= 0
Second issue is you are using dfs() twice, but the visited field is static - it is all set to true before the second run of dfs() you need to initialize it back to false in all fields before the second run, or the algorithm will terminate instantly without doing anything [since all the nodes are already in visited - and the algorithm will decide not to re-explore these nodes.].
Your code counts diagonal cells as neighbours too. If you want only left/right/top/bottom cells than you can check
if(!(dr == 0 && dc == 0) && ok(r+dr, c+dc) && dr * dc == 0)
You also need to count first cell. You don't count cell you start from.
I think you are after a flood-fill algorithm (perhaps with the slightly odd constraint that there must be at least two neighbours of the same colour)? I'm not sure why depth-first-search is appropriate here.