I want to check if a variable ("matrix") is changed when sent to a specific function ("moveAround"),
so I created another variable ("matrixB") and I gave it the value that comes from the function given the first variable,
and now I compare the two variables.
The problem is that for some reason the first variable is changed as well as the second.
The code looks like this:
matrixB = moveAround(matrix, userDir);
cmpMatrices(matrix, matrixB);
The function "moveAround" is meant to return a different matrix then given (most of the time).
the function "cmpMatrices" returns true if the two matrices are alike, and false there is at least one component that does not equal.
For some reason when I get "matrixB" from the "moveAround" function after giving it "matrix" it changes both "matrix" and "matrixB".
The function "moveAround" calls another function name "moveUp"/"moveDown"/"moveRight"/"moveLeft" in respect to "userDir".
The function "moveUp" looks like this:
public static int[][] moveUp(int[][] matrix) {
int i, j, m;
for (j = 0; j < matrix.length; j++) {
m = 1;
for (i = 0; i + m < matrix.length;) {
if (matrix[i + m][j] == 0) {
m++;
} else {
if (matrix[i + m][j] == matrix[i][j]) {
matrix[i][j] = 2 * matrix[i][j];
matrix[i + m][j] = 0;
i++;
} else {
if (matrix[i][j] == 0) {
matrix[i][j] = matrix[i + m][j];
matrix[i + m][j] = 0;
m++;
} else {
if (m != 1) {
matrix[i + 1][j] = matrix[i + m][j];
matrix[i + m][j] = 0;
i++;
} else {
i++;
}
}
}
}
}
}
return matrix;
}
The other move Down/Right/Left are very similar just different direction.
The function "cmpMatrices" looks like this:
public static boolean cmpMatrices(int[][] matrixA, int[][] matrixB){
for(int i = 0; i < matrixA.length; i++){
for(int j = 0; j < matrixA[i].length; j++){
if(matrixA[i][j] != matrixB[i][j]){
return false;
}
}
}
return true;
}
moveAround alters the passed matrix and returns it. A bit redundant: either return void, or make a new matrix object.
Variables in java typically hold a value, the matrix object.
Assigning to an other variable will share that matrix object.
int[][] a = new int[][]{{1, 2},{3, 4}};
int[][] b = deepCopy(a);
a[0][0] = 10;
System.out.println(Arrays.deepToString(b));
static int[][] deepCopy(int[][] a) {
int[][] clone = a.clone();
for (int i = 0; i < a.length; ++i) {
clone[i] = clone[i].clone();
}
return clone;
}
You need to copy the object before modifying it.
This might help you
How do I do a deep copy of a 2d array in Java?
Related
I have two 2d boolean arrays, the smaller array (shape) is going over the larger array (world).
I am having trouble to find a method to find out when the smaller array can "fit" into the larger one.
When I run the code it either just goes through the larger array, never stopping, or stops after one step (incorrectly).
public void solve() {
ArrayList<Boolean> worldList=new ArrayList<>();
ArrayList<Boolean> shapeList=new ArrayList<>();
for (int i = 0; i < world.length; i++) {
for (int k = 0; k < world[i].length; k++) {
worldList.add(world[i][k]);
display(i, k, Orientation.ROTATE_NONE);
for (int j = 0; j < shape.length; j++) {
for (int l = 0; l < shape[j].length; l++) {
shapeList.add(shape[j][l]);
if(shapeList.equals(worldList)) {
return;
}
}
}
}
}
}
A good place to start with a problem like this is brute force for the simplest case. So, for each index in the world list, just check to see if every following index of world and shapes match.
Notice we only iterate to world.size()-shapes.size(), because naturally if shapes is longer than the portion of world we haven't checked, it won't fit.
import java.util.ArrayList;
public class Test {
ArrayList<Boolean> world = new ArrayList<>();
ArrayList<Boolean> shapes = new ArrayList<>();
public static void main(String[] args) {
new Work();
}
public Test() {
world.add(true);
world.add(false);
world.add(false);
world.add(true);
shapes.add(false);
shapes.add(true);
// Arraylists initialized to these values:
// world: T F F T
// shapes: F T
System.out.println(getFitIndex());
}
/**
* Get the index of the fit, -1 if it won't fit.
* #return
*/
public int getFitIndex() {
for (int w = 0; w <= world.size()-shapes.size(); w++) {
boolean fits = true;
for (int s = 0; s < shapes.size(); s++) {
System.out.println("Compare shapes[" + s + "] and world["+ (w+s) + "]: " +
shapes.get(s).equals(world.get(w+s)));
if (!shapes.get(s).equals(world.get(w+s))) fits = false;
}
System.out.println();
if (fits) return w;
}
return -1;
}
}
When we run this code, we get a value of 2 printed to the console, since shapes does indeed fit inside world, starting at world[2].
You can find the row and column of fitting like this
public void fit() {
int h = world.length - shape.length;
int w = world[0].length - shape[0].length;
for (int i = 0; i <= h; i++) {
for (int k = 0; k <= w; k++) {
boolean found = true;
for (int j = 0; j < shape.length && found; j++) {
for (int l = 0; l < shape[j].length && found; l++) {
if (shape[j][l] != world[i + j][k + l])
found = false;
}
}
if (found) {
//Your shape list fit the world list at starting index (i, k)
//You can for example save the i, k variable in instance variable
//Or return then as an object for further use
return;
}
}
}
Hello Everyone I'm having toughest time in my career figuring this out.
Here I have commented on the code so the problem could be easily spotted.
I wish someone can rescue me, thanks to that rescuer in advance.
Code below
public class Marathon {
/** The whole point here is: how can I return a new arr which is of type Marathon */
static int [][] raceValues;
public Marathon(int aValue){
this.raceValues = [aValue][aValue]; // (Problem no.1) Erroneously accessing a static variable nonstatically
for (int i = 1; i <= aValue; i++) {
for (int j = 1; j <= aValue; j++) {
this.raceValues[i-1][j-1] = (aValue * (i - (aValue - (aValue - 1)))) + j;
}
}
}
Marathon alterAnyValue(int a){
/*
* If I could write something like next line, then my problem would be solved. But eclipse will grizzle
* "Cannot convert from int to Marathon"
* Marathon arr[][] = raceValues;
*/
int arr[][] = raceValues;
for (int i = 0; i < aValue; i++) {
for (int j = 0; j < aValue; j++) {
int c = arr[i][j] % 3; // Divisible by three
int d = arr[i][j] % 5; // Divisible by five
if(c == 0){
arr[i][j] = 3;
}
if(d == 0){
arr[i][j] == 5;
}
}
}
/*
* Here I don't know how to return new arr
* I must return a new arr and it must be of type Maraton
* At this point the whole world just ended. I don't know what to do
*/
//return new Marathon()
//return arr
}
}
For your first Problem: The static accessing: You can do Marathon.raceValues = new int[aValue][aValue]; This would solve your Static Access "error"
For your second problem I don't see a possibility in Java as you can't make new "Integer" classes as they are final. You COULD make your own Integer but I couldn't imagin WHY. So the other possibility could be that you return an Integer Array.
This would be what I would try to do. If you want something different please specify the question a bit better :)
I am trying to implement an iterative Sudoku solver. To avoid recursion I used a stack, but I'm having problems with its management. The starting board is represented by a String array (variable 'input' in the following code) in which each element is composed of 3 numbers: the [row, col] and its value (i.e, "006" means that the element in the 1st line and 1st col is 6) and is translated into an array of int by the constructor. When I run it, I cannot get a solution, so there are probably mistakes in the nested for cycles. Any help is appreciated.
import java.util.ArrayList;
public class SudokuSolver {
private int[][] matrix = new int[9][9];
private String[] input = { "006", "073", "102", "131", "149", "217",
"235", "303", "345", "361", "378", "422", "465", "514", "521",
"548", "582", "658", "679", "743", "752", "784", "818", "883" };
private ArrayList<int[][]> stack = new ArrayList<>();
public SudokuSolver() {
// Building the board based on input array
for (int n = 0; n < input.length; ++n) {
int i = Integer.parseInt(input[n].substring(0, 1));
int j = Integer.parseInt(input[n].substring(1, 2));
int val = Integer.parseInt(input[n].substring(2, 3));
matrix[i][j] = val;
}
stack.add(matrix);
}
private boolean isSolution(int[][] cells) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if(cells[i][j] == 0)
return false;
}
}
return true;
}
private boolean isValid(int i, int j, int val, int[][] cells) {
for (int k = 0; k < 9; k++)
if (val == cells[k][j])
return false;
for (int k = 0; k < 9; k++)
if (val == cells[i][k])
return false;
return true;
}
private boolean iterativeSudokuSolver() {
int[][] current = null;
while(stack.size() > 0 && !isSolution(stack.get(0))) {
current = stack.remove(0);
for (int row = 0; row < 9; row++) {
for (int col = 0; col < 9; col++) {
if (current[row][col] == 0) {
for (int val = 1; val <= 9; val++) {
if (isValid(row, col, val, current)) {
current[row][col] = val;
stack.add(0, current);
break;
}
}
}
}
}
}
if (current != null && isSolution(current))
return true;
else
return false;
}
public static void main(String [] args) {
SudokuSolver sudokuSolver = new SudokuSolver();
boolean result = sudokuSolver.iterativeSudokuSolver();
if (result)
System.out.println("Sudoku solved");
else
System.out.println("Sudoku not solved");
}
}
A stack implementation by adding and removing the 0-th element of an ArrayList is a very bad idea: it forces the whole content of the array to be shifted back an forth every time. Use LinkedList or modify the end of the list.
When you add and remove the same instance of the matrix back and forth to the stack, it is still the same matrix object, even though you may call it "current" or any other name. This means that when you change something in the matrix and then remove it from your stack, the change stays there (and in every other element of your stack, which are identical links to the same object). The logic of your solution looks like it needs to store the previous state of the solution on the stack, if so - allocate a new array every time and copy the data (also not very efficient, but try starting there).
A good question has to be specific. "Why this doesn't work?" is a bad question. Fix the obvious problems first, debug, and if puzzled provide more information about the state of your program (data in, data on step #1...N, for example)
I am trying to program following well-known counting islands problem.
and it is not giving me the expected output. Where am I going wrong?
My assumption is if 0's touch 0th row or column or dimension of matrix .. it will not be treated as island
Here is my code
public class Matrix {
static int rowCount = 5;
static int columnCount = 4;
static int[][] matrix = { {1,1,1,1,1},
{1,0,0,0,1},
{1,1,1,1,1},
{1,1,1,0,1}
};
static boolean[][] visited = new boolean[rowCount][columnCount];
private static int countIslands = 0;
public static void main(String[] args) {
try{
for(int i=0; i<rowCount; i++){
for(int j=0; j<columnCount; j++){
if(matrix[i][j]==0){
checkZeros(matrix, i, j);
System.out.println("returned " + i + j);
}
}
}
System.out.println(visited);
}catch(Exception e){
}
System.out.println(countIslands);
}
private static void checkZeros(int[][] matrix2, int i, int j) {
boolean valueWithinLimits = withinLimits(i,j);
System.out.println("checking for " + i + j);
if(valueWithinLimits) && checkAlreadyVisited(i,j)){
if(matrix[i][j+1]==0){
checkZeros(matrix2, i, j+1);
}
if(matrix[i+1][j+1]==0){
checkZeros(matrix2, i+1, j+1);
}
if(matrix[i+1][j]==0){
checkZeros(matrix2, i+1, j);
}
if(matrix[i+1][j-1]==0){
checkZeros(matrix2, i-1, j-1);
}
visited[i][j] = true;
System.out.println("i reached here when ij are : " + i + j);
countIslands ++;
}
}
private static boolean checkAlreadyVisited(int i, int j) {
System.out.println("visited found for " + i + j);
return visited[i][j-1] || visited[i-1][j-1] || visited[i-1][j] || visited[i-1][j+1];
}
private static boolean withinLimits(int i, int j) {
return (i>0 && i<rowCount-1 && j>0 && j<columnCount-1);
}
}
The below solution is tested and works perfectly fine for any possibility
package com.divyanshu.island;
/**
* <b>Assumption 1 : 1 is Land, 0 is water.</b>
* <b>Assumption 2 : It is all water outside the matrix.</b>
*
* Instantiate IslandCounter by passing a m*n matrix.
* Method getIslandCount gives you the count of island formed.
*
* </br></br>Or</br></br>
*
* Method getIslandCount gives the count of all connected 1s in a m*n matrix with values in 1 or 0.
*/
public class IslandCounter {
private Integer[][] matrix;
public IslandCounter(Integer[][] matrix) {
this.matrix = matrix;
}
public int getIslandCount() {
int count = 0;
if (matrix == null || matrix.length == 0) {
return count;
}
Integer[][] tempMatrix = matrix.clone();
for (int i = 0; i < tempMatrix.length; i++) {
for (int j = 0; j < tempMatrix[i].length; j++) {
if (detectIsland(tempMatrix, false, i, j, matrix.length - 1, matrix[i].length - 1)) {
count++;
}
}
}
return count;
}
private boolean detectIsland(Integer[][] tempMatrix,
boolean islandDetected,
int i,
int j,
int iMax,
int jMax) {
if (i > iMax || j > jMax || i < 0 || j < 0 || tempMatrix[i][j] == 0) {
return islandDetected;
} else {
tempMatrix[i][j] = 0;
islandDetected = true;
detectIsland(tempMatrix, islandDetected, i - 1, j, iMax, jMax);
detectIsland(tempMatrix, islandDetected, i, j - 1, iMax, jMax);
detectIsland(tempMatrix, islandDetected, i + 1, j, iMax, jMax);
detectIsland(tempMatrix, islandDetected, i, j + 1, iMax, jMax);
}
return islandDetected;
}
}
===================================================================================
/**
*
*/
package com.divyanshu.island;
import java.util.Random;
/**
*This is a Main-Class to test the IslandCounter.
*/
public class IslandTest {
/**
* #param args
*/
public static void main(String[] args) {
Integer[][] matrix = generateMatrix();
printMatrix(matrix);
IslandCounter counter = new IslandCounter(matrix);
System.out.println("Total islands in the matrix : " + counter.getIslandCount());
}
private static Integer[][] generateMatrix() {
Integer[][] matrix = new Integer[4][4];
Random random = new Random();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
matrix[i][j] = random.nextInt(2);
}
}
return matrix;
}
private static void printMatrix(Integer[][] matrix) {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
}
}
What you can do to improve is to add an exclusion array: an array of elements that are zeros. For example, if you find a zero within limits, you can start looking around and see if there are any zeros. Keep looking until you find all of them. Then add every single one of these zeros to the exclusion array, and when you continue with the loop, make sure it skips the elements in the exclusion array. This is not code, but the outline of the logic of the program.
I think there are multiple problems in your code.
Your visited matrix is full of false, which mean that checkAlreadyVisited will always return false. Also, I don't understand why does this method checks surroundings to see if the current location is visited. Using a temporary matrix like visited is a good idea, but you should print both map to ensure that it works.
countIslands is never incremented because of the previous error, but once you'll have resolved it, it will be incremented on every call (which should match the number of 0 on your map). If you want his solution to work with the border constraint, you must apply his detectIsland on each border before the for loop.
Divyanshu's solution works, except that it counts 1 and doesn't consider that an island touching a border is not an island (as you said).
To correct your solution, the visited matrix must be a copy of the matrix before using it, checkAlreadyVisited should only scan [i][j] and not its surrondings, and you shouldn't increment countIslands at each call.
Again, print your maps at each turns and use an easier matric like:
static int[][] matrix = {{1,1,1},
{1,0,1},
{1,1,1},};
(Didn't saw this question was three monsth old... anyway, here you go)
I have an object calld Matice. Matice is a matrix nxn filled with random numbers in a set range. I want to perform some operations on my objects like adding, multiplying, inversion, etc. How can i do that? If i try something like m1[i][j] * m2[j][i].
but i get error message.
public class Main {
public static void main(String[] args) {
Matice m1 = new Matice(3);
m1.matrixFill(0, 5);
m1.matrixPrint();
//m1.matrixAdd(m2);
}
}
public class Matice {
int[][] matice;
private int n;
public Matice(int n) {
this.n = n;
if(n > 0) {
matice = new int[n][n];
}
}
public void matrixPrint(){
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.format("%5d", matice[i][j]);
}
System.out.println("");
}
System.out.println("");
}
public void matrixFill(int a, int b){
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
matice[i][j] = (int) (Math.random() * (a + b + 1) - a);
}
}
}
public void matrixAdd(Matice m1, Matice m2){
int[][] resultMatrix = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
resultMatrix[i][j] = m1[i][j] + m2[i][j];
}
}
}
}
You are referring to the object itself not the array that is the field of object.
Try this:
resultMatrix[i][j] = m1.matice[i][j] + m2.matice[i][j];
instead of
resultMatrix[i][j] = m1[i][j] + m2[i][j];
btw. I recommend to mark matrixAdd to static because it is a stateless, helper method or extract into a different class.
You already started the right way: by adding the operations as methods to your Matice class. Unlike C++, you can not define operators for your class. You'll have to stick with ordinary methods.
Your methods should use the Matice they are called on as one argument. Thus use something like add(Matice other) Next you'll have to decide if you methods modify the Matice they are called on, or if they return a copy of the data.
Last but not least, if this isn't a toy/exercise project, I'd check out existing libraries: Java matrix libraries