Store matrices and compare them in java - java

I need to store many matrices and then to compare some of them by retrieving the last matrix added and the previous one.
I create these matrices using:
int[][] matrix = new int[10][10];
My matrices have only 0s, 1s and 2s. I want to compare matrices based on the value of each position. In my case, two matrices are different as long as at least one position has a different value.
Each matrix is created bases on elements detected via Reactivision. Elements that are not moved are 2s, elements which are added are 1s, and where there isn't anything it's a 0.
For example:
1 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
and
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 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
would be different.
The number of matrices stored is not fixed. If I have 10 matrix already created, what is the most efficient way to store these and to be able to compare them ?
I've searched for this on StackOverFlow and other forums but can't find any answer

Since many (maybe most) entries in your matrices are zeroes, it is inefficient to store them as is. You need to use a sparse matrix representation. Here is a pretty exhaustive list of matrix libraries, many of which allow for sparse representations.
Most of them will also already have an equals() method, which you can override to suit your definition (or not, if their definition is already the same as yours).
Finally, since you need to compare only the last two matrices, you need some sort of a queue. I would maintain a list, and use a ListIterator for this.

Since you have not provided any code, I can only help you with design.
So, Here is some design tips for you:
Store your matrices in two-dimensional arrays
Ex: int[][] matrix = new int[5][3]; this gives you a 5x3 matrix.
Since you don't know how many matrices you will have, add them into an arraylist.
Ex: ArrayList<int[][]> matrices = new ArrayList<>();
I don't know what you mean with comparison but, you can do it using a nested for loop by retrieving the matrices from the arraylist one by one to compare.

I would write a different class Matrix and would override equals and hashcode methods.
You may want to use sparse matrix representation if most of the values in your matrix would be zero.

Related

How to change the values of a multidimensional array in a range?

I want to change the values of a 2d array from a given starting position (rowPos and colPos) for a certain amount of rows and columns.
So far I have the code below:
int[][] block = new int[10][10];
int rowPos = 3, colPos = 3;
int rows = 4, columns = 4;
for (int i = rowPos; i < rows; i++)
for (int j = colPos; j < columns; j++)
block[i][j] = 1;
for (int[] x : block) {
for (int y : x)
System.out.print(y + " ");
System.out.println();
}
However this gives me the following output:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 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 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
It is only setting the value at rowPos and colPos. This is my expected output:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 1 1 1 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 0 0 0 0 0 0 0 0 0
I feel like I'm close but missing something small, please help me!
Change the loops to this:
for (int i = rowPos; i < rows + rowPos; i++)
for (int j = colPos; j < columns + colPos; j++)
block[i][j] = 1;
In your code, you let i and j start at the row and column you want to begin changing the values. That's fine, but it also means your condition doesn't work anymore. Let me show you what happens:
You declare i and set it's value to 3.
You check if i (3) is less than rows (4). Success!
You declare j and set it's value to 3.
You check if j (3) is less than columns (4). Success!
You set block[3][3] to 1.
j is incremented by 1 and is now 4.
You check if j (4) is less than columns (4). Fail!
i is incremented by 1 and is now 4.
You check if i (4) is less than rows (4). Fail!
You print the array's contents.
The problem is that because you start i and j at values greater than 0, you need to keep that in mind when performing the check.

how to restricts the number of character and lines reads from a file before insertinting into 2dimentional array in java

i have go through the previous answers but nothing like what i am looking for, specifically in java. here is my code, the block of my code can read a singe character integer only which is not exactly what i intend to do, i intends to reads more than one char integer, it doesn't work. and i want reads only 16 lines and 16 integers in a line from the file even if the file contains more than 16 lines and more than 16 integers per line. can some one share an idea with me please?
Here is sample input data:
13 20 0 0 0 0 0 0 0 0 0 0 11 2
0 0 0 0 0 0 0 0 0 4 5 0 0 11 2
0 0 0 0 0 0 0 0 0 333 4 0 0 0 0
0 0 0 0 0 0 0 0 0 9 10 41 3 5 8
0 0 0 0 0 0 0 0 0 0 11 2 333 4
13 20 0 0 0 0 0 0 0 0 0 0 11 2
0 0 0 0 0 0 0 0 0 4 5 0 0 11 2
0 0 0 0 0 0 0 0 0 333 4 0 0 0 0
0 0 0 0 0 0 0 0 0 9 10 41 3 5 8
0 0 0 0 0 0 0 0 0 0 11 2 333 4
13 20 0 0 0 0 0 0 0 0 0 0 11 2
0 0 0 0 0 0 0 0 0 4 5 0 0 11 2
0 0 0 0 0 0 0 0 0 333 4 0 0 0 0
0 0 0 0 0 0 0 0 0 9 10 41 3 5 8
0 0 0 0 0 0 0 0 0 0 11 2 333 4
13 20 0 0 0 0 0 0 0 0 0 0 11 2
0 0 0 0 0 0 0 0 0 4 5 0 0 11 2
0 0 0 0 0 0 0 0 0 333 4 0 0 0 0
0 0 0 0 0 0 0 0 0 9 10 41 3 5 8
0 0 0 0 0 0 0 0 0 0 11 2 333 4
i just want insert this into the 2dimentional array as you can see in my code, but my array is 16X16 but the file may be more than 16x16 in size, but i just want reads just 16x16 even if the file contains more than that, and ignore the empty line even if it exist.
BufferedReader bufferedReader = new BufferedReader(new FileReader("text.txt"));
String line = null;
int[][] board = new int[16][16];
int k = 0;
while((line = bufferedReader.readLine())!=null) {
String[] newmatrix = line.split(" ");
for(int i=0; i<9; i++) {
board[k][i] = Integer.parseInt(newmatrix[i]);
}
k++;
}
This appears to be "a learning exercise". So, hints / advice only1:
To stop reading after 16 lines, use a counter.
Skip an empty line by testing for an empty line.
Use a Scanner (hasNextInt() and nextInt() to process each line.
It is a good idea to avoid hard-wiring literal constants into your code ... like 9 which you seem to have pulled out of the air.
Use board.length - 1 or board[i].length - 1 for your array bounds when "looping". (See previous)
Also ... your input file seems to only have 14 integers per line, not 16 as the question states.
1 ... because you will learn more by coding this yourself.
The code below should work.
BufferedReader bufferedReader = new BufferedReader(new FileReader("text.txt"));
String line = null;
int[][] board = new int[16][16];
int k = 0;
while((line = bufferedReader.readLine())!=null) {
String[] newmatrix = line.split(" ");
for(int i = 0; i < 16; i++) {
board[k][i] = Integer.parseInt(newmatrix[i]);
}
k++;
if (k == 16)
break;
}
bufferedReader.close();

Java JPG DCT coefficients alter by themselfs after I modify them

I have a program that changes the DCT coefficients of a JPG image.
This is the code that gives me the DCT coefficients
public int[] quantizeBlock(double inputData[][], int code) {
int outputData[] = new int[blockSize * blockSize];
int i, j;
int index;
index = 0;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
// The second line results in significantly better compression.
outputData[index] = (int) (Math.round(inputData[i][j]
* (((double[]) (Divisors[code]))[index])));
// outputData[index] = (int)(((inputData[i][j] * (((double[])
// (Divisors[code]))[index])) + 16384.5) -16384);
index++;
}
}
return outputData;
}
This is a DCT matrix before modifications
-43 7 0 0 0 0 0 0
-8 1 2 -1 0 0 0 0
-1 -1 -1 1 0 0 0 0
-2 1 0 -1 0 0 0 0
6 0 0 0 0 0 0 0
-2 0 1 0 0 0 0 0
-1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
This is after the modifications
-42 8 0 0 0 0 0 0
-7 1 3 0 0 0 0 0
0 0 0 1 0 0 0 0
-1 1 0 0 0 0 0 0
7 0 0 0 0 0 0 0
-1 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
After I save the image using image Buffer,I use the created image to get back the modified DCT from it but all I get is:
-41 9 0 0 0 0 0 0
-6 1 4 0 0 0 0 0
0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 0
8 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
I've seen a question where the user using a library in IOS did the same thing and had the same problem.Apparently the library recopressed the image and the hidden message was destroyed.
I don't know if this is the case for me.I use Image Buffer to create the image.
A couple things off the top that could be happening. The first is rounding errors. The JPEG process introduces small errors. All your values are one off. This could come from rounding.
The second is quantization. Your values may be quantized (divided). Your example does not indicate the compression stages that may be taking place in between your examples.

Cloning/Copying an Object

I am creating a connect 4 game in Java and i'm trying to make a deep copy of a custom object (The game Board), then modify that copy and add it to a list as part of the mini max algorithm.
This is the code i'm using for copying:
public void getPossibleBoards(Board board) {
for(int i = 0; i < 7; i++) {
if(!board.columns.get(i).isFull()) {
Board tmpBoard = board.copy(board);
tmpBoard.columns.get(i).addCounter(turn);
boardList.add(tmpBoard);
}
}
}
public Board copy(Board other) {
Board b = new Board(other);
b.columns = other.columns;
return b;
}
This takes the main board (passed as a parameter), loops through the columns on the board and if the column isn't full it creates a new board object and puts a counter in a empty column, then adds this new board object to a list for later use.
The problem is that when I copy the board, it keeps referencing the main board and modifying that, then each loop it adds a counter to a column without wiping the board clear first.
Expected output is: (Player 1 is human, player 2 is the computer)
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
2 0 0 0 0 0 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 0 0 0 0
0 0 0 0 0 0 0
0 2 0 0 0 0 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 0 0 0 0
0 0 0 0 0 0 0
0 0 2 0 0 0 1
And so on until the 7 loops are over.
Actual output:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 2
2 2 2 2 2 2 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 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 2
2 2 2 2 2 2 1
and so on until the 7 loops are over.
EDIT:
I had problems with the solution below so I decided to try another way, but got the same result and I don't understand why.
I'm basically creating a new Board object, within the constructor i'm assigning new blank columns to it, then looping through the main_board to get the colours of the counters at each slot (Stored as integers in the Slot class), and altering the new Board respectively.
if(!board.columns.get(i).isFull()) {
Board tmpBoard = new Board();
for(int j = 0; j < 7; j++) {
for(int k = 0; k < 7; k++) {
tmpBoard.columns.get(j).slots.get(k).setColour(board.columns.get(j).slots.get(k).getColour());
}
}
}
Board constructor
public Board() {
for(int i = 0; i < 7; i++) {
columns.add(new Column());
}
}
EDIT: Nevermind, above solution worked, just me forgetting to add a new counter after the copy.
The line b.columns = other.columns; causes the problem since you are doing a reference assignment (i.e. its not doing a deep copy as you are expecting). You can copy that array by using System.arraycopy method.
I think in your case you are using an ArrayList to represent columns/rows if so, you can use:
Collections.copy(arrayList2,arrayList1);
or simply
new ArrayList<Integer>(oldList)
in order to create a copy.
Why does Board take another Board as a constructor parameter?
Your problem is that you don't copy the columns, you only do b.columns = other.columns in your copy method. If one of the two boards is changed both boards are affected. Create a new column instances when copying and also deep copy all elements in an column until you reach immutable objects or primitives.

Dynamic programming: Find largest diamond (rhombus)

I have a small program to do in Java. I have a 2D array filled with 0 and 1, and I must find the largest rhombus (as in square rotated by 45 degrees) and their numbers.
Example:
0 1 0 0 0 1
1 0 1 1 1 0
1 0 1 1 1 1
0 1 1 1 1 1
0 0 1 1 1 1
1 1 1 1 1 1
Result:
1
1 1 1
1 1 1 1 1
1 1 1
1
The problem is similar to this SO question.
If you have any idea, post it here.
This too long for a comment. I'll post my solution later on if you can't solve it but here's how I've done it (in less than 15 lines of code): I first created a second array (a little big bigger [n+2][n+2]) and did n/2 pass:
0 0 0 0 0 0 0 0
0 0 1 0 0 0 1 0
0 1 0 1 1 1 0 0
0 1 0 1 2 2 1 0
0 0 1 2 2 2 1 0
0 0 0 1 2 2 1 0
0 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 1 0 0 0 1 0
0 1 0 1 1 1 0 0
0 1 0 1 2 2 1 0
0 0 1 2 3 2 1 0
0 0 0 1 2 2 1 0
0 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0
Where a non-zero number x means "I'm the center of a rhombus of size x" (I'm expressing the size in relation with the length of the diagonals [which are both equal in your case] of the rhombus). You can find if you have the center of a rhombus of size (k+1) by checking if {top,right,down,left} are all the centers of rhombus of size k.
The advantage of first creating a bigger array is that it really simplifies your logic but I could do it in place, with a more convoluted logic, by modifying the original array or by using a second array of the same size as the input (once again, it's way easier to simply put a safe "fence" of all-zeroes around your input).
If you don't "surround" your array with a fence, you have a lot of additional if/else checks: this would be prone to errors, lead to bigger code and lead to uglier code.
Short tutorial:
How would you solve the problem if it was a 1x1-field?
How could you formulate the problem recursively?
How could you remember intermediate results and use them?
Do it.
void rhombus()
{
maxr=0;
for (int i=n-1;i>=0;i--)
{
for (int j=n-1;j>=0;j--)
{
if (b[i][j]>0)
{
if ((i==n-1) || (j==n-1) || (i==0) || (j==0)) b[i][j]=1;
else {
b[i][j]=min4(b[i][j+1],b[i][j-1],b[i+1][j],b[i-1][j])+1;
if (b[i][j]==maxr) nrr++;
else if (b[i][j]>maxr) {
nrr=1;
maxr=b[i][j];
}
}
}
}
}
}
Did it,it works,this is my function,where maxr is the max size of the rhombus,and nrr is the number of max sized rhombus.Not sure how it works on huge arrays.(i loop this function n/2 times)

Categories

Resources