Checking symmetry in a grid with java - java

I need help with a game I'm doing:
The game is the following,
There are two players, 'B' and 'N'.
There is a grid of characters.
Both players take turn to place a char (B or N depending on who they are) on the grid.
Every time they place a char, I have to check whether there a symmetry is occuring. For example. There are differents types of symmetries. Horizontal and Vertical in every 2*2, 3*3 and 4*4 squares that contains the char that was just placed here. In the case of the 3*3 symmetry, the middle row or column does not take place in the symmetry.
I have done everything until now except the symmetries. I'm having some difficutly at doing them. I have an idea on how to do them but individually. Does any of you know how I could do the symmetries in one method only?

The java code for something similar to what you described for an n by n sized grid would go something like:
boolean isHorizontallySymmetrical(char[][] grid, int n){
int across = n / 2;
for(int i = 0; i < n; i++){
int right = 0
for(int left = 0; left < across; left++){
right = n - left - 1;
if(grid[i][left] != grid[i][right]){
return false;
}
}
}
return true;
}
A similar sort of thing would be needed for a vertical symmetry function.

Related

I don't understand what the multiplication in q.offer(x*m + y) does and what the while loop is doing and everything in the code

Can someone explain this code in detail, I don't understand what the multiplication in q.offer(x*m + y) does and what the while loop is doing. This is the requirements for the program:
Starting from a given location on the grid, experiment explores the grid, expanding and labeling all of the cells in a single colony originating from the starting location. Taking as input a grid, the coordinates of a starting location, and a label, experiment will either label that location and all its neighbors or do nothing, depending on the presence or absence of a cell at the given location, respectively; either way, experiment is required to return the size of the labeled colony.
(c) The program is responsible for ensuring that experiment is called start- ing at every location on the grid storing a 1. The reason is that experiment locates only a single colony.
For example, using the first grid above and calling experiment for the first time on the location at the top row and forth column will modify the grid only at the locations labeled A, leaving all the other locations intact.
Once every grid location storing a 1 has been colonized, the program freezes the grid by replacing the 0s on the grid with s (dashes) .
(d) The program is responsible for creating an initial grid of random number of rows and columns in the range [5-20], and for filling the grid randomly with 0s and 1s.
(e) The program is responsible for generating the labels for experiment to use during exploration. Use the alphabet letters A · · · Z and a · · · z as labels (in that order).
public static Map<Character, Integer> experiment(int n, int m, int x, int y, char[][] matrix, int[][] mark, char colony) {
Queue<Integer> q = new LinkedList<Integer>();
q.offer(x*m + y);
mark[x][y] = 1;
matrix[x][y] = colony;
while(!q.isEmpty()) {
int front = q.peek(); q.remove();
int x1 = front / m, y1 = front % m;
if(x1 != 0)
if(mark[x1-1][y1] == 0 && matrix[x1-1][y1] == '1') {
matrix[x1-1][y1] = colony;
mark[x1-1][y1] = 1;
q.offer((x1-1) * m + y1);
}
I just don't understand this part of code. Can someone please explain it.
one possible explanation could be that
x and y are coordinates of grid,
if you loop over x and y as below
for( int x = 0 ; x < width; x++ ){
for( int y = 0 ; y < height; y++ ){
index_of_one_dimensional_array = x*m+y;//where m = width(i.e number if columns in each row)
}
}
seems like the q.offer() functions somehow uses this concept to set a value depending on value of index_of_one_dimensional_array given by x*m+y;
and loop is used to make sure every cell in the grid is processed which happens when the queue is empty

Finding adjacent elements in a 2d array and counting them.

Im stumped on what to do for this part of my homework and could really use some help. I need to cycle through a given 2d array and find all similar elements that are adjacent to another and count that so for example
AA--B
AA--B
-AA--
----C
So the count would be 3 one for the As one for the Bs and one for the C, I just kinda need an idea where to start So far i have
public static int howManyOrganisms(char[][] image){
int count = 0;
for (int i = 0; i < image.length; i++) {
for (int j = 0; j < image[i].length; j++) {
if(image[i][j] != '-') {
count++;
}
System.out.println();
}
return howManyOrganisms(image, count);
}
}
I need help figuring out how to track the total number of elements that are within contact of one another (so left, right, down, up) being another similar element.
In each iteration, you can use your i,j variables to "navigate" the 2d plane and see if any interacting items are the same. In each iteration you would check the following indexes to see if they are the same:
image[i-1][j] (one row up)
image[i+1][j] (one row down)
image[i][j-1] (one left)
image[i][j+1] (one right)
Of course for all of these statements first you should check if +1/-1 is still within the size of your matrix, otherwise you will end up with out of bounds exception.

How do you find the number of rectangles in a 2D matrix of 0s and 1s?

I have searched a number of posts here on SO as well as other resources online. Most of them provide a solution for finding the maximum area of a rectangle in a 2D matrix, which I understand. However, I am curious to know the way you find the number of rectangles in a 2D matrix where a rectangle is represented by 1s.
Update:
Apologize for not clarifying the scenario as to what classifies as a rectangle - it is considered a rectangle if the cells inside a certain perimeter are filled with 1s.
Some pseudo-code:
for x_0 in rows:
for x_1 > x_0 in rows: # symmetry-reduction: x_0 always "top"
for y_0 in columns:
for y_1 > y_0 in columns: # symmetry reduction: y_0 always "left"
if mat[x_0, y_0] == mat[x_0, y_1] == mat[x_1, y_0] == mat[x_1, y_1] == 1:
found rectangle!
Keep in mind: it's pseudo-code (partially based on python-style) and the boolean-evaluation does not work like that in most languages!
The symmetry-reduction is not only improving performance, but it's also important when you are counting. There are visually equal rectangles, where x_0 and x_1 just take different roles (left and right point). You have to decide how to count this.
Edit: After Ole V.V.'s comment above i realized that there are indeed very different interpretation's. Most of these can be realized with the pseudo-code above but with a different check on the inner-level. But that might be your work then (and there are more-tuned approaches possible then in some cases)!
Here i assume, a rectangle is just defined by 1's at the 4 corners!
Edit: After your new definition of a rectangle, the inner-check changes to:
if all(mat[x_0:x_1, y_0:y_1]) # python/numpy inspired pseudo-code!
So basically you might check all the values defined by the 4 border-points. That's easy and solves your problem.
But of course you could be much more efficient. It might be wise to add some binary-flag which indicates if the current rectangle (they are growing) is still filled with only 1's. Actually you would probably need 2 binary-flags, 1 for each dimension. Then you can do early-stopping if that's not the case.
Here is a non-optimized version that should give the correct result:
int sum = 0;
for (int row = 0; row < n; row++) {
for (int col = 0; col < m; col++) {
// count all rectangles with top left corner at (row,col)
int upperLimit = m; // this number sets the max width that rectangles with greater
// height can have (depends on the 1s in the rows above)
for (int r = row; r < n && matrix[r][col] == 1; r++) {
int c = col;
for (; c < upperLimit && matrix[r][c] == 1; c++)
sum++;
upperLimit = c;
}
}
}

Iterative Depth First Search To Find A String (2D Array)

I'm trying to create an iterative approach to a boggle game. The class contains fields for a 2d Array of Strings called "board" and has a 2d array of booleans called "haveVisit". The method that calls test 2 loops through the whole board, finding positions of the first character of the target string, then passes the coordinates into the test2 method, returning a list holding coordinates.
The return1Index method takes a 2D array coordinate at creates a int representative of the coordinates from a corresponding 1d array from it. The return2DIndex does the opposite and returns an int array holding the two coordinates.
public List<Integer> test2(int row1, int row2, String findMe){
String temp = findMe;
List<Integer> output = new ArrayList<Integer>();
if (board[row1][row2].charAt(0) != findMe.charAt(0))
return output;
haveVisit = new boolean[size][size];
int row = row1;
int column = row2;
output.add(return1DIndex(row, column));
haveVisit[row][column] = true;
//for each letter in the string
for(int j = 0; j < temp.length(); j++)
//for every column and row combination
for (int x = row - 1; x < row + 2 ; x++)
for (int y = column - 1; y < column + 2 ; y++)
//if index is valid and not visited
if (x > -1 && y > -1 && y < size && x < size && !haveVisit[x][y])
//if the output is the same size as string, return
if(output.size() == findMe.length())
return output;
//if the character in the board matches the char we're looking for
if(board[x][y].charAt(0) == temp.charAt(j))
{
haveVisit[x][y] = true;
output.add(return1DIndex(x, y));
//update row and column indices
row = x;
column = y;
}
}
}
return output;
}
For some reason this method works only 50% of the time. The method works fine with finding the letters when they're arranged left to right or top to bottom, but finding words from right to left or bottom to top never works except for one case: when you're searching for a string of length 1 or 2, where this method always works.
I have a working recursive solution but I wanted to try this way. Any thoughts as to why this wouldn't work?
Edit: Code now works from right to left, but still does not work when attempting to search upwards.
I don't know exactly what the problem is, but there are a few suspects:
You are updating row and column indices while checking their neighbors. This is like removing an element from an array while iterating through it: it's well defined, but has tricky semantics. I suggest either bailing out (greedy algorithm) or keeping a stack of matches (deeper search, requires saving stack of visited cells too).
The fors are missing opening braces, but the closing braces are there, suggesting missing code.
I'm not familiar with boggle, but isn't it possible for a letter to have two similar neighbors, like AXA? By just doing output.add(return1DIndex(x, y)); you may be outputting two ways to get the same letter. You may end up with output longer than findMe.
My suggestion is to follow a more standard format of depth-first search while you iron out the bugs. Wikipedia has a non-recursive pseudocode implementation, for example: https://en.wikipedia.org/wiki/Depth-first_search#Pseudocode .

Formula to draw pyramid of circles

I'm trying to create a pyramid of circles to my game, looking similar to this :
alt text http://img266.imageshack.us/img266/3094/lab1213c.jpg
But I can't make it print properly. Constantly I'm getting really strange spirals but nothing close to this. Can anyone give me some tip on proper formula ? My window is 600x600, base of pyramid is 8 .
fields = new Field[BASE*(BASE/2)+4];
int line_count = BASE;
int line_tmp = line_count;
for(int i=0; i< fields.length; i++){
for( int j=line_tmp; j <= line_count; j++){
fields[i] = new Field(0, (150+(line_tmp*5)),(600+line_tmp*5));
}
line_count--;
line_tmp = line_count;
}
The mistakes I see are:
Incorrect array size formula.
Including line_tmp (which seems to be your column counter) in your y expression.
Having two variables, line_count and line_temp that are always equal.
Having your outer loop count by node rather than counting by row.
Having generally meaningless variable names and magic numbers strewn about.
// I use java.util.ArrayList because using its add(..) method is convenient here.
// The proper forumula for anticipated number of nodes is: base×(base+1)÷2
final List<Field> fields = new ArrayList<Field>(BASE*(BASE+1)/2);
// I use a java.awt.Point to store the (x,y) value of the first node of the row.
// This clarifies the meaning, rather than using ints or long inline expressions.
final Point rowStart = new Point(PANEL_WIDTH/2, DIAMETER);
// The number of rows equals the number of nodes on the final row.
for (int row = 1; row <= BASE; row++) {
// The nth row has n nodes.
for (int circle = 0; circle < row; circle++) {
// Each row starts at rowStart and each subsequent circle is offset to
// the right by two times the circle diameter.
fields.add(new Field(0, rowStart.x + circle*DIAMETER*2, rowStart.y));
}
// Each subsequent row starts a little down and to the left of the previous.
rowStart.x -= DIAMETER;
rowStart.y += DIAMETER;
}
Remember to only use this as reference for fixing your own code if this is homework.

Categories

Resources