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)
Related
I am writing a program that has to decode QR Codes. The codes are internally represented as a 2D Boolean List. The codes will usually be read as text files containing 1s and 0s, where 1 means a dark module (true) in the matrix, and 0 a light module (false).
I have to implement a method, which will take an InputStream and then has to return a QR Code back. I'll have to read .txt which contains 1s, 0s and comment lines beginning with '#'. I need to make the method ignore those comment lines, but I am not sure how to do it.
Here are some relevant parts of the code:
First the QR Code constructor (All of the methods used in the constructor work and do their job):
public class QRCode {
private List<List<Boolean>> data; //A 2D Boolean matrix, true means black, false means white.
public QRCode(List<List<Boolean>> data)
{
if (data == null)
throw new NullPointerException();
if (QRCode.isQuadratic(data) == false)
throw new InvalidQRCodeException("Matrix must be quadratic!");
if (QRCode.versionCheck(data) < 1 || QRCode.versionCheck(data) > 40)
throw new InvalidQRCodeException("Invalid Dimensions (Version).");
if (QRCode.correctlyAlligned(data) != true)
throw new InvalidQRCodeException("Improper Allignment!");
if (QRCode.correctTimers(data) != true)
throw new InvalidQRCodeException("Incorrect Timing Pattern!");
if (QRCode.correctFormatting(data) != true)
throw new InvalidQRCodeException("Incorrect Formatting!");
this.data = data;
}
}
This is the method I'm referring to. What I wrote sofar at least. Also, if the .txt file contains anything other than 1s, 0s and comment, it should throw an exception.
PS: I've never used InputStreams before, I tried googling this but all answers I found were for specific types of Streams, and they use a .readLine() method, which my IS here is not letting me use.
public static QRCode fromFile(InputStream is) throws IOException
{
int i;
List<List<Boolean>> data = new ArrayList<>(); //a 2D Boolean Matrix
int y = -1, x = -1;
if (is == null)
throw new NullPointerException();
while((i = is.read())!=-1) //Reading begin
{
if (i == (byte) '\n') //If a line in .txt file ends.
{
y++;
data.add(new ArrayList<Boolean>());
x = 0;
}
if ((char) i == '1') //|| (char) i == '0')
{
data.get(y).add(true);
x++;
}
if ((char) i == '0') //||
{
data.get(y).add(false);
x++;
}
}
return new QRCode(data);
}
An example of text files that I'd be handling:
# name: small
# type: bool matrix
# rows: 25
# columns: 25
1 1 1 1 1 1 1 0 1 1 1 1 0 1 1 0 1 0 1 1 1 1 1 1 1
1 0 0 0 0 0 1 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 1
1 0 1 1 1 0 1 0 0 1 0 1 0 1 0 1 0 0 1 0 1 1 1 0 1
1 0 1 1 1 0 1 0 0 0 1 1 0 1 0 0 0 0 1 0 1 1 1 0 1
1 0 1 1 1 0 1 0 0 0 1 1 1 0 0 0 1 0 1 0 1 1 1 0 1
1 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1
1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 1 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0
1 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 0 0 0 0 1
1 1 1 1 0 0 0 0 1 0 1 0 0 1 1 1 0 0 0 1 1 1 0 0 0
1 0 0 1 1 1 1 0 1 1 0 0 1 1 0 1 1 0 1 1 1 0 1 0 1
0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 1 0 1 1 1 1 0
0 1 1 0 0 1 1 1 0 1 1 0 0 0 0 0 1 0 1 1 0 1 0 1 1
1 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 0
1 1 1 0 0 0 1 1 0 1 0 0 0 1 1 1 1 0 1 0 0 0 0 1 1
1 0 1 1 0 1 0 0 0 0 1 0 1 0 1 0 1 0 0 1 0 1 1 0 1
1 0 1 1 0 1 1 1 1 0 0 1 1 1 0 1 1 1 1 1 1 0 1 1 1
0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0 1 0 1
1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1
1 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 1 0 0 0 1 1 0 0 0
1 0 1 1 1 0 1 0 1 0 0 1 0 1 0 1 1 1 1 1 1 1 0 1 1
1 0 1 1 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 0 1 1 1
1 0 1 1 1 0 1 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 0 1 1
1 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 0 1 1 1 1
1 1 1 1 1 1 1 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 1
First, I suggest you use a Reader to read text. Then you can use a BufferedReader with its readLine() method to work with lines of text, rather than a stream of bytes.
Regardless, given your current code: once your read a \n, set a boolean flag to indicate that you've just saw a new line character. Then, as you begin reading the next line, switch on that flag such that if it's true, and you see a # as the next character, you should read until you see another \n. If it the flag is not true, then read the rest of the line as you are doing.
You may want to consider whitespace when finding the #, depending how lax you want this to be.
Why not use Files.lines instead of InputStream?
Files.lines(Paths.get("path_to_File.txt")).filter(s -> !s.contains("#"));// let's
//read all lines form the file and skip the lines with `#` symbol
Than we can convert each line to a list of Boolean:
s -> Stream.of(s.split(" ")).map("1"::equals).collect(Collectors.toList())// split
string by ` ` (space) symbol and convert to Boolean "1" - true, "0" - false
Now let's put everything together:
List<List<Boolean>> qr = Files.lines(Paths.get("data/fromFile.txt"))
.filter(s -> !s.contains("#")).map(
s -> Stream.of(s.split(" ")).map("1"::equals)
.collect(Collectors.toList())
).collect(Collectors.toList());
For the file:
# name: small
# type: bool matrix
# rows: 1
# columns: 3
1 1 1
1 0 1
Output will be
[true, true, true]
[true, false, true]
If you decide to use Reader then you may use regex to eleminate the lines which includes any character except '0' and '1'. You can find detail about regex usage below link.
How to check if a string contains only digits in Java
You can modify regex expression for only 1 and 0 like String regex = "[0-1]+";
After you can use below sample code to get each character.
String s1="hello";
char[] ch=s1.toCharArray();
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.
public class UnaryOperator {
public static void main(String[] args) {
byte a= -5;
System.out.println(~a); // prints 4
}
}
When I do it manually, I get the answer as 6.
Here is how I did it:
128 64 32 16 8 4 2 1
0 0 0 0 0 1 0 1
As it is a negation I inverted it to the following:
128 64 32 16 8 4 2 1
0 0 0 0 0 1 0 1
sign -1 1 1 1 1 0 1 0
-----------------------------
0 0 0 0 1 0 1
add one--> 0 0 0 0 0 1 1
------------------------------
0 0 0 0 1 1 0 = 6
------------------------------
I know there's something wrong with what I am doing but I am not able to figure it out.
5 is 00000101
-5 is 11111010+00000001 = 11111011
~(-5) is 00000100
so you get 4.
You're starting out with -5, which is in two's complement. Thus:
-128 64 32 16 8 4 2 1
1 1 1 1 1 0 1 1 (= -5)
flip: 0 0 0 0 0 1 0 0 (= +4)
I haven't done much bitwise stuff, but after reading wikipedia for a few seconds it seems like NOT -5 = 4, on wikipedia they used NOT x = -x - 1. So the program is correct.
Edit: For unsigned integers, you use NOT x = y - x were y is the maximum number that integer can hold.
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.
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.