Counting (8 possible) neighbours in 2D array in conways Game Of Life - java

I have to count how many "alive" (in this case a char: 'O') neigbours each single cell has. Every cell has 8 neighbours. (It is for "The Game Of Life" from Conway)
"As you can notice, each cell has eight neighbors. We consider the universe to be periodic: border cells also have eight neighbors. For example: Neighbours from a "normal" cell
If cell is right-border, its right (east) neighbor is leftmost cell in the same row.
If cell is bottom-border, its bottom (south) neighbor is topmost cell in the same column.
Corner cells use both solutions." When a cell is border and when a cell is a top corner
The links are visualizations to how to check the cells in cases of "exceptions".
I found this on the internet:
for (int x = -1; x <= 1; x += 1) {
for (int y = -1; y <= 1; y += 1) {
int r = i + y;
int c = j + x;
if (r >= 0 && r < n && c >= 0 && c < n
&& !(y == 0 && x == 0)
&& currentUniverse[i][j] == 'O') {
neighbours++;
}
However that did not seem to work...
I can not come up with a tidy and most of all smart/handy/short piece of code to check how many alive neighbours a cell at a position (let's say currentUniverse[i][j]) has...
Has anyone suggestions, tips or some other help?

Give this one a shot. I am using n as the size of the array (assumes in square).
int n = 4;
System.out.println();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int neighbours = 0;
for (int x = -1; x <= 1; x += 1) {
for (int y = -1; y <= 1; y += 1) {
if (!(y == 0 && x == 0)) {
int r = i + y;
int c = j + x;
//normalize
if (r < 0) r = n - 1;
else if (r == n) r = 0;
if (c < 0) c = n - 1;
else if (c == n) c = 0;
if (currentUniverse[r][c] == 0)
neighbours++;
}
}
}
System.out.print("\t" + neighbours);
}
System.out.println();
}

Related

Incorrect result from dynamic programming algorithm

I am trying to solve the Dynamic Problem question to find unique paths between origin and the last cell of a board. The problem is present on leetcode here https://leetcode.com/problems/unique-paths/.
The problem statement is -
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?
I am stuck on a test case with m = 23 and n = 12. Can you please explain the inconsistency in my code?
public int uniquePaths(int m, int n) {
return getPath(m,n,1,1);
}
HashMap<String,Integer> map = new HashMap<>();
private int getPath(int m, int n, int x, int y){
if(x == n && y == m) return 1;
else if(x > n || y > m) return 0;
String s = ""+x+y;
if(map.get(s) != null) return map.get(s);
int max =0;
if(x < n)
max = max + getPath(m,n,x+1,y);
if(y < m)
max = max + getPath(m,n,x,y+1);
map.put(s,max);
return max;
}
}
On m = 23 and n = 12, I am getting 192184665 as output whereas 193536720 is the expected result.
Look into my comment. You can solve this in Sigma (m * n) with bottom-up dp.
Create an int matrix of size [m * n].
int[] a = new int[n][m];
for (int i = 0; i < n-1; ++i) {
a[i][m-1] = 1;
}
for (int j = 0; i < m-1; ++j) {
a[n-1][j] = 1;
}
for (int i = n-2; i >= 0; --i) {
for (int j = m-2; j >= 0; --j) {
a[i][j] = a[i+1][j] + a[i][j+1];
}
}
System.out.print(a[0][0]);

Traversing a 2D array matrix diagonally from bottom left to upper right

I have a 3x4 matrix represented by a 2D array:
. 0 1 2 3
0 a c f i
1 b e h k
2 d g j l
and my approach to traverse the diagonal slice was to treat each slice as a sum, like this:
a = (0+0) = 0
b,c = (0+1),(1+0) = 1
d,e,f = (0+2),(1+1),(2+0) = 2
g,h,i = (1+2),(2+1),(3+0) = 3
j, k = (2+2),(3+1) = 4
l = (3+2) = 5
However, my code right now prints it in the opposite way that I want it to, which is from upper right to bottom left.
Current Output is:
acbfedihgkjl
Desired Output is:
abcdefghijkl
for (int sum = 0; sum <= numRows + numColumns - 2; sum++) {
for (int i = 0; i < numRows; i++) {
int j = sum - i;
if ((i >= 0 && i < numRows) && (j >= 0 && j < numColumns)) {
System.out.print(array[i][j]);
}
}
}
Can somebody point me in the right direction on how to fix my code to get the output that I want?
While it isn't very pretty, I think this will do it:
int i = 0;
int j = 0;
while (true) {
System.out.println("" + array[i][j]);
--i;
++j;
if (i < 0) {
if (j == numCols)
break;
i = Math.min(j, numRows - 1);
j = Math.max(j - numCols + 2, 0);
} else if (j >= numCols) {
if (i == numRows - 2)
break;
i = numRows - 1;
j = Math.max(j + 2 - numCols + i, 0);
}
}
int i = 0;
int j = 0;
int n = 0;
int x = 3;
int y = 4;
int newSize = Math.max(x,y) * Math.max(x,y);
while(n < newSize){
if(i <= x && j <= y)
System.out.println(array[i][j]);
n++;
if(i == 0) {
i = n:
j = 0;
} else {
--i;
++j;
}
}

What is the Complexity of my function?

I want to find the Complexity of my function and i am not sure if it's O(n) or maybe something else
public static boolean find(int [][] mat, int x)
{
int i = 1;
int j = 0;
int k = 0;
int row = 0;
int col = 0;
int n = mat.length;
while(i < n)//(see method discription)stage 1. loops over maxuim of n/2 times = O(n)
{
i = i * 2;
if(x == mat[i-1][i-1])
return true;
else if (x < mat[i-1][i-1])
{
k = i / 2;
row = col = i-1;
break; //bigger value then x found, x is within the max and min values of the matrix. moving on to find a match.
}
}
if (i > n)//x is bigger then max value of mat
return false;
for (j = k; j > 1; j = j / 2)//stage 2. locking on the right 2x2 matrix. runs k times. k<n O(n)
{
if(x == mat[row-j][col] || x == mat[row][col-j])
return true;
else if(x < mat[row-j][col])
row = row - j;
else if (x < mat[row][col-j])
col = col - j;
}
//checking if x is within this 2x2 matrix
if(x == mat[row][col-1])
return true;
else if(x == mat[row-1][col])
return true;
else if(x == mat[row-1][col-1])
return true;
else
return false;
}
I would say O(log2(n)):
first loop does log2(n) max iterations
second loop depends on k < log2(n) and does max log2(k) operations

Searching a word in a given string array

You are given a 2D array as a string and a word via keyboard. The word
can be in any way (all 8 neighbors to be considered) but you can’t use
same character twice while matching. Return word's first and last
character's index as (x,y). If match is not found return -1.
That's the question. I'm having trouble with searching. I tried that:
int x=0,y=0;
for(int f=0; f<WordinArray.length; f++){
for(int i=0; i<matrix.length; i++){
for(int j=0; j<matrix[0].length; j++){
if(matrix[i][j].equals(WordinArray[f])){
x=i; y=j;
System.out.print("("+x+","+y+")");
}
}
}
}
But, That code is not working as it is supposed to. How else I can write this searching code?
Referring to Sixie's code
Assuming this is a valid input/output to your program?
Size:
4x4
Matrix:
a b c d
e f g h
i j k l
m n o p
Word: afkp
(0,0)(3,3)
I edited your code, so that it should work for input on this form (it is case sensitive at the moment, but can easily be changed by setting .toLowerCase()
Scanner k = new Scanner(System.in);
System.out.println("Size: ");
String s = k.nextLine();
s.toUpperCase();
int Xindex = s.indexOf('x');
int x = Integer.parseInt(s.substring(0, Xindex));
int y = Integer.parseInt(s.substring(Xindex + 1));
System.out.println("Matrix:");
char[][] matrix = new char[x][y];
for (int i = 0; i < x; i++) {
for (int p = 0; p < y; p++) {
matrix[i][p] = k.next().charAt(0);
}
}
System.out.print("Word: ");
String word = k.next();
int xStart = -1, yStart = -1;
int xEnd = -1, yEnd = -1;
// looping through the matrix
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
// when a match is found at the first character of the word
if (matrix[i][j] == word.charAt(0)) {
int tempxStart = i;
int tempyStart = j;
// calculating all the 8 normals in the x and y direction
// (the 8 different directions from each cell)
for (int normalX = -1; normalX <= 1; normalX++) {
for (int normalY = -1; normalY <= 1; normalY++) {
// go in the given direction for the whole length of
// the word
for (int wordPosition = 0; wordPosition < word
.length(); wordPosition++) {
// calculate the new (x,y)-position in the
// matrix
int xPosition = i + normalX * wordPosition;
int yPosition = j + normalY * wordPosition;
// if the (x,y)-pos is inside the matrix and the
// (x,y)-vector normal is not (0,0) since we
// dont want to check the same cell over again
if (xPosition >= 0 && xPosition < x
&& yPosition >= 0 && yPosition < y
&& (normalX != 0 || normalY != 0)) {
// if the character in the word is not equal
// to the (x,y)-cell break out of the loop
if (matrix[xPosition][yPosition] != word
.charAt(wordPosition))
break;
// if the last character in the word is
// equivalent to the (x,y)-cell we have
// found a full word-match.
else if (matrix[xPosition][yPosition] == word
.charAt(wordPosition)
&& wordPosition == word.length() - 1) {
xStart = tempxStart;
yStart = tempyStart;
xEnd = xPosition;
yEnd = yPosition;
}
} else
break;
}
}
}
}
}
}
System.out.println("(" + xStart + "," + yStart + ")(" + xEnd + ","
+ yEnd + ")");
k.close();
I think you need to plan your algorithm a bit more carefully before you start writing code. If I were doing it, my algorithm might look something like this.
(1) Iterate through the array, looking for the first character of the word.
(2) Each time I find the first character, check out all 8 neighbours, to see if any is the second character.
(3) Each time I find the second character as a neighbour of the first, iterate along the characters in the array, moving in the correct direction, and checking each character against the word.
(4) If I have matched the entire word, then print out the place where I found the match and stop.
(5) If I have reached the edge of the grid, or found a character that doesn't match, then continue with the next iteration of loop (2).
Once you have your algorithm nailed down, think about how to convert each step to code.
If I understood your question right. This is a quick answer I made now.
int H = matrix.length;
int W = matrix[0].length;
int xStart = -1, yStart = -1;
int xEnd = -1, yEnd = -1;
String word = "WordLookingFor".toLowerCase();
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (matrix[i][j] == word.charAt(0)) {
int tempxStart = i;
int tempyStart = j;
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
for (int k = 0; k < word.length(); k++) {
int xx = i+x*k;
int yy = j+y*k;
if(xx >= 0 && xx < H && yy >= 0 && yy < W && (x != 0 || y != 0)) {
if(matrix[xx][yy] != word.charAt(k))
break;
else if (matrix[xx][yy] == word.charAt(k) && k == word.length()-1) {
xStart = tempxStart;
yStart = tempyStart;
xEnd = xx;
yEnd = yy;
}
} else
break;
}
}
}
}
}
}
A little trick I used for checking all the 8 neighbors is to use two for-loops to create all the directions to go in:
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
if(x !=0 || y != 0)
System.out.println(x + ", " + y);
}
}
This creates
-1, -1
-1, 0
-1, 1
0, -1
0, 1
1, -1
1, 0
1, 1
Notice: All but 0,0 (you don't want to revisit the same cell).
The rest of the code is simply traversing though the matrix of characters, and though the whole length of the word you are looking for until you find (or maybe you don't find) a full match.
This time the problem is that how could I print word's first and last
letter's indexes. I tried various ways like printing after each word
was searched. But, all of them didn't work. I am about to blow up.
int[] values = new int[2];
for(int i=0; i<matrix.length; i++){
for(int j=0; j<matrix[0].length; j++){
if(Character.toString(word.charAt(0)).equals(matrix[i][j]) == true || Character.toString(ReversedWord.charAt(0)).equals(matrix[i][j]) == true ){
System.out.print("("+ i + "," +j+")");
//First letter is found.Continue.
for(int p=1; p<word.length(); p++){
try{
for (int S = -1; S <= 1; S++) {
for (int SS = -1; SS <= 1; SS++) {
if(S !=0 || SS != 0)
if(matrix[i+S][j+SS].equals(Character.toString(word.charAt(p))) && blocksAvailable[i+S][j+SS] == true ||
matrix[i+S][j+SS].equals(Character.toString(ReversedWord.charAt(p))) && blocksAvailable[i+S][j+SS] == true) {
values[0] = i+S;
values[1] = j+SS;
blocksAvailable[i+S][j+SS] = false;
}
}
}
}catch (ArrayIndexOutOfBoundsException e) {}

how to write a conditional telling java that the array index is invalid

(this is a 2d array filled with objects) So the places marked "//Out of Grid" is where I don't know how to tell java that the index its looking for is not in the grid and to move on.
A basic over view of what im trying to accomplish is go thru each cell starting[0][0] and check all of its adjacent neighbors, as for the first check its neighbors would be [0][1],[1][0], and [1][1]. and then if the age of the object in the index is 0, do something..
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
int neighbor_x = x + i;
int neighbor_y = y + j;
if (neighbor_x < 0 || neighbor_x >= board.length) {
// Out of Grid
}
if (neighbor_y < 0 || neighbor_y >= board[neighbor_x].length) {
// Out of Grid
}
if (board[neighbor_x][neighbor_y].age == 0) {
nCount++;
if (board[x + i][y + j].getPreviousValue() == 0)
hCount++;
}
}
}
Unless you want to perform some operations, you can simply leave them out.
Out of bound exception can occur in the case where neighbor_x < 0 and neighbor_y >=0, when the second statement is being ran, the first condition is verified and the second throws an exception. You can simply use the only condition that matters
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
int neighbor_x = x + i;
int neighbor_y = y + j;
if ((neighbor_x >=0 && neighbor_x < board.length) &&
(neighbor_y >= 0 && neighbor_y < board[neighbor_x].length) &&
board[neighbor_x][neighbor_y].age == 0 ) {
nCount++;
if (board[x + i][y + j].getPreviousValue() == 0)
hCount++;
}
}
}
If this ever throws an exception, then just separate the conditions comme suite
if ( neighbor_x >=0 && neighbor_x < board.length )
if(neighbor_y >= 0 && neighbor_y < board[neighbor_x].length)
if(board[neighbor_x][neighbor_y].age == 0 )

Categories

Resources