How to search a 2D array inside a 2D array efficiently? - java

I am trying to search a 2D array inside a 2D array, and I have tried the following code to do so:
loopX: for (int x = 0; x < str1.length - str2.length + 1; ++x)
loopY: for (int y = 0; y < str1[x].length - str2[0].length + 1; ++y)
{
for (int xx = 0; xx < str2.length; ++xx)
for (int yy = 0; yy < str2[0].length; ++yy)
{
if (str1[x + xx][y + yy] != str2[xx][yy])
{
k++;
continue loopY;
}
}
// Found the submatrix!
System.out.println("Found at: " + x + " " + y);
break loopX;
}
System.out.println(k);
In this code str1 is the larger 2D array inside which I am trying to search and match the smaller 2D array str2. Both are char arrays.
k is the element I need to keep track of in case, there is no match.
I would also like to know what can be the most efficient way to do so.
For this the algorithm I thought, that first I should match only the starting element of both the arrays, and when they match then only go and match other elements.
But, I am not able to write specific code for this.
I would appreciate if someone could help me in this.

Related

Jump Encryption help? Code not making sense

Jump Encrypt: prompt the user to enter an integer (jump value) that is between 2 and the square root of the length of the current message, inclusive. Now imagine that we are going to write the current message in a table form, using the same number of rows as the jump value. The character order in the original message would be the order of the
first column, followed by the second column, etc. For example, with jump value of 5, the original message would be in table form:
T i e g a
h s i m g
i o n e e
s t r a s .
h i l s
To complete the encryption, display the encrypted message row by row, "Tieg ahs imgi oneestras. hils" for the above. Hint: this can be accomplished in one step with nested loops! No arrays or actual tables are required in the solution,
So I have attached the code that I have used down below, but it seems to be that I am off by one column when it comes to printing the message.
public static String jumpEncrypt(String message, int jumpValue) {
String jencrypt = "";
for (int i = 0; i < jumpValue; i++) {
for (int j = 0; j < (jumpValue); j++) {
jencrypt += message.charAt(i + j*jumpValue);
}
}
return jencrypt;
}
The expected output for the original message with a jumpValue of 5 should be "Tieg ahs imgi oneestras. hils" but I am getting an output of "Tieg hs imi onestras hils"
You are iterating both i and j up to the jumpValue. That means that the maximum message you can encrypt is jumpValue * jumpValue) - or 25 in your case - characters, and your string is already longer (you can see that your "correct" matrix is 6x5).
So you need to iterator j not up to jumpValue, but up to the message length divided by jumpValue - and you need to round it up to the nearest whole number.
That also means that some of the characters in the last column of your matrix come from a position longer than the length of the input string, so you need to check for that.
The below code tackles both:
public static String jumpEncrypt(String message, int jumpValue) {
String jencrypt = "";
for (int i = 0; i < jumpValue; i++) {
for (int j = 0; j < (message.length() + jumpValue - 1) / jumpValue; j++) {
int index = i + j * jumpValue;
if (index < message.length()) {
jencrypt += message.charAt(index);
}
}
}
return jencrypt;
}
Note that the expression (message.length() + jumpValue - 1) / jumpValue (which is message.length() / jumpValue, but rounded up) is constant throughout both loops, so for efficiency, it's better to extract it into a local variable before the loops, to avoid an unnecessary evaluation of the expression for every loop.
So with this for loop code their is not much to go on but a simple fix might be
maybe j should be equal to one so message.charAt(i + j*jumpValue); it should not equal to
0 + 0*jumpValue) since that makes everything 0 and clears everything out to the basic.
so jencrypt = 0; no matter what its initial value was.
so maybe jumpValue - 1 for int i = 0;
Trying doing the math portion of the floor loop and see why its not adding up correctly.
for (int i = 0; i < jumpValue - 1; i++) {
for (int j = 0; j < (jumpValue); j++) {
jencrypt += message.charAt(i + j*jumpValue);
}
}
return jencrypt;
I am not completely sure if I am right but I did my best to understand I am pretty new still to coding! :)
If I use for (int j = 0; j <= (jumpValue); j++), and make no other changes, it works for me.

How to run through a 2d array with a single loop?

I was wondering if I could write this very thing but with one single loop, instead of two?
for (int row = 0; row < matrix.length; row++) {
for (int col = 0; col < matrix[0].length; col++) {
if ((row + col) % 2 == 0) {
System.out.print(matrix[row][col] + ", ");
sum += matrix[row][col];
}
}
System.out.println("with a sum of " + sum);
}
Actually just ignore the body of the loop.. It's totally irrelevant, I have no idea whatsoever why I included it.. How to somehow combine the two for loops is my question.
Just keep it simple, if possible. Thank you!
You can, though it's inefficient:
for(int i = 0 ; i < matrix.length * matrix[0].length ; i++)
sum += matrix[i % matrix.length][i / matrix.length];
The basic idea would be to map each index to a value in a 2d-number space, using the fact that we know the length of each "row" of the array (matrix.length). We can compose a single index, that uniquely identifies two indices matrix[x][y], by z = x + y * matrix.length. The reverse of this would then be:
x = z % matrix.length
y = z / matrix.length
This depiction would be complete, e.g. each z in [0 , matrix.length * matrix[0].length) would identify exactly one pair of indices, thus we can use it here.
Paul's answer is initially how I thought to do it. But there is the slight restriction that you need to have a rectangular two-dimensional array (i.e. the sub-arrays are all the same length). If you're modelling a "matrix", this is likely to be the case, but more generally you may want to sum up non-rectangular arrays.
A way around this is to do something like this:
for (int r = 0, c = 0; r < matrix.length;) {
if (c < matrix[r].length) {
sum += matrix[r][c];
++c;
} else {
c = 0;
++r;
}
}
Although it's getting a bit messy. I'd just go for a nested loop instead.

Generating an X and Y ID in a certain way

I had a lot of trouble trying to find a solution to this answer because it's hard to search specifically about it. I will try my best to explain it well though.
Currently I have the following code:
for(int x = 0; x < 10000; x++){
for(int z = 0; z < 10000; z++){
if(!exists(x + ";" + z)){
return x + ";" + z;
}
}
}
This is pretty much what I want to do except the way the numbers will "generate" is like so:
0;0
0;1
0;2
0;3
...
0;9999
1;0
1;1
I would like the numbers to generate in the following way "or similar" while still ensuring that every combination exists.
0;0
1;0
1;1
0;1
I created an image to show how the numbers should generate. It can go from bottom to left or left to bottom. (See image)
Thanks!
int len = 3;
for (int i = 0; i < len; i++) {
for (int j = 0; j <= i; j++) //println(i+";"+j);
for (int k = i-1; k >= 0; k--) //println(k+";"+i);
}
In the code above len serves the purpose of defining the length of a square (len is 3 above which represents a 3 x 3). In your own code you picked 10000 but that is too large for printing values
What you want is easiest to do with two internal loops, one that handles vertical and the other horizontal. Other than that just arbitrarily pick which one handles the corner of each i iteration. In the code above the j loop handles the corner case
The algorithm you seem to be looking for is:
for(int distanceFromCorner = 0; distanceFromCorner < 10000; distanceFromCorner++) {
for(int otherAxis = 0; otherAxis <= distanceFromCorner; otherAxis++) {
if(!exists(distanceFromCorner + ";" + otherAxis))
return distanceFromCorner + ";" + otherAxis;
if(!exists(otherAxis + ";" + distanceFromCorner))
return otherAxis + ";" + distanceFromCorner;
}
}
Note that this (like your original algorithm) will be much slower than necessary if you want to generate a large number of IDs. (Optimizing this is a separate question)

Finding all possible combinations of elements of six arrays

I have 6 arrays, each has 8 elements. I'd like to write a method that reveals all the possible combinations of all the elements of all arrays like:
firstArray firstElement, secondArray firstElement,.... sixthArray firstElement
firstArray secondElement, secondArray firstElement,.... sixthArray firstElement
....etc...
firstArray lastElement, secondArray lastElement,.... sixthArray lastElement
How can I do this in the most efficient way, the most performance-friendly way?
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < B.length; j++) {
for (int h = 0; h < C.length; h++) {
for (int k = 0; k < D.length; k++) {
for (int l = 0; l < E.length; l++) {
for (int n = 0; n < F.length; n++) {
System.out.println(A[i] + " "
+ B[j] + " "
+ C[h] + " "
+ D[k] + " "
+ E[l] + " "
+ F[n]);
}
}
}
}
}
}
Simplest Code would be:
for (first array a) {
for (second array b) {
for (third array c) {
for (fourth array d) {
for (fifth array e) {
for (sixth array f) {
System.out.println(a[], b[], c[], d[], e[], f[]);
}
}
}
}
}
}
This is not good performance wise as it will take - no. of arrays * element per array * element per array time.
This is fast becoming an SO FAQ, but for the life of me I can't find the right question that this is a duplicate of, so here's the FPA (frequently provided answer).
Generate all the 6-digit base-8 numbers from 000000 to 777777 in turn. Each number specifies one of the sets you are looking for: the first digit identifies the element of the first array, the second digit the element of the second array, etc.
That should be enough to get you started, any 'help' I provided in Java would be laughed at. Whether this is better than the answer you already have (or indeed, materially different from it), I leave you and others to judge.
For your future reference you are trying to compute the cartesian product of your 6 arrays. As to the efficiency of these approaches, well computing the cartesian product of 2 sets each of n elements is O(n^2) and there is no getting around that by clever programming. So for 6 sets, each of n elements, the computational complexity is going to be O(n^6).

best way to check the indices around a certain index in a 2d array

I'm working on this bacteria life game thing I have to make.
Basically I have a 2d string array let's say 20 by 20.
What would be the best way to check all 8 spots around a certain index. Each index is suppose to represent a bacteria. For each bacteria(index) I have to check to see if any of the 8 spots around this index has another bacteria in it, if the index has a bacteria in it, it's represented simply by a "*", asterik.
What would be the best way to go about checking all 8 spots around each index, because based on what is in the indices around a certain index I have to make certain changes etc.
The only idea I have come up with is having a bunch of if statements to check all 8 spots, I was wondering if there is a better way to do this
ex:
row 1 - www , row 2 = wOw , row 3 - www ,
if I am at the O index, what would be the best way to check all the index spots around it for a certain string.
Sorry, I am not very good at explaining my problems, bad english :o.
thanks for any of the help.
so you have something like this
char[][] table = new char[20][20]
for(int i = 0; i < 20; i++) {
for(int j = 0; j < 20; j++) {
int surroundingBacteria = 0;
for(int x = max(i-1,0); x < min(20,i+1); x++) {
for(int y = max(i-1,0); y < min(20,i+1); y++) {
if(table[x][y] == '*') surroundingBacteria++;
}
}
switch(surroundingBacteria) {
// put your case logic here
}
}
}
Here is how I've accomplished this in the past:
for(int x = -1; x<=1; x++){
if ( i+x < xLength && i+x >= 0){
for(int y = -1; y<=1; y++){
if(j+y < yLength && j+y >= 0){
//logic goes here
}
}
}
}

Categories