Given a binary grid[ ][ ] of size N*M, with each cell containing either 0 or 1, where 1 represents an alive cell and the 0 represents a dead cell. The task is to generate the next generation of cells based on the following rules:
- Any live cell with fewer than two live neighbors dies due to under-population.
- Any live cell with two or three live neighbors lives on to the next generation.
- Any live cell with more than three live neighbors dies due to overpopulation.
- Any dead cell with exactly three live neighbors becomes a live cell by reproduction.
Here, the neighbor of a cell includes its adjacent cells as well as diagonal ones, so for each cell, a total of 8 neighbors are there.
Examples:
Input: N = 5, M = 10
0000000000
0001100000
0000100000
0000000000
0000000000
Output:
0000000000
0001100000
0001100000
0000000000
0000000000
Explanation:
The cells at (1, 3), (1, 4) and (2, 4) are alive and have 2 neighbors,
So, according to Rule 2, they live on to the next generation.
The cell at (2, 3) is dead and has exactly 3 neighbors,
So, according to Rule 4, it becomes a live cell.
Input: N = 4, M = 5
00000
01100
00010
00000
Output:
00000
00100
00100
00000
Explanation:
The cells at (1, 1) and (2, 3) have only 1 neighbor,
So, according to Rule 1, they die.
The cell at (1, 2) is alive and has 2 neighbors,
So, according to Rule 2, it lives on to the next generation.
The cell at (2, 2) is dead and has exactly 3 neighbors,
So, according to Rule 4, it becomes a live cell.
Naive Approach:
We have already discussed an approach to this problem in Program for Conway’s Game Of Life | Set 1. In this approach, an extra grid future[ ][ ] of size N*M is created to store the next generation of cells.
Time complexity: O(N*M)
Auxiliary Space: O(N*M)
Efficient Approach:
A space-optimized approach is possible for this problem, which uses no extra space. For every alive cell, increment its value by 1 each time we encounter an alive neighbor for it. And, for every dead cell, decrement its value by 1 each time we encounter an alive neighbor for it. Now, if the value in a cell is smaller than 0, it means it is a dead cell and if the value is greater than 0, it is an alive cell, also the magnitude of value in a cell will represent the number of its alive neighbors. In this way, an extra grid will not be required and a space-optimized solution is obtained. Detailed steps of this approach are as follows:
For the present grid position, we will look at all the neighbors.
- Traverse the whole grid.
- If the value of the neighbor is >= 1(i.e. initial value of the neighbor was 1)
- If, the current cell is >= 1, just increment the current cell value by 1.
Now, grid [ i ][ j ] > 0 will imply that initial grid [ i ][ j ] == 1. - Else, the current cell is <= 0, just decrement the current cell value by 1.
Now, grid [ i ][ j ] <= 0 will imply that initial grid [ i ][ j ] == 0.
- If, the current cell is >= 1, just increment the current cell value by 1.
- Now, generate the required new generation grid using the modified grid.
- If the current cell value is > 0, there are 3 possible cases:
- If the value is < 3 then change it to 0.
- Else if the value is <= 4 then change it to 1.
- Else change the value to 0.
- Else, the current cell value is <= 0.
- If the value is 3 then change it to 1.
- Else change it to 0.
- If the current cell value is > 0, there are 3 possible cases:
Below is the implementation of the above approach:
// C++ implementation of // the above approach #include <bits/stdc++.h> using namespace std;
void print(vector<vector< int >> grid)
{ int p = grid.size(),
q = grid[0].size();
for ( int i = 0; i < p; i++) {
for ( int j = 0; j < q; j++) {
cout << grid[i][j];
}
cout << endl;
}
} // Function to check if // index are not out of grid static bool save(vector<vector< int > > grid, int row, int col)
{ return (grid.size() > row && grid[0].size() > col && row >= 0 && col >= 0);
} // Function to get New Generation
void solve(vector<vector< int > >& grid)
{ int p = grid.size(),
q = grid[0].size();
int u[] = { 1, -1, 0, 1, -1, 0, 1, -1 };
int v[] = { 0, 0, -1, -1, -1, 1, 1, 1 };
for ( int i = 0; i < p; i++)
{
for ( int j = 0; j < q; j++)
{
// IF the initial value
// of the grid(i, j) is 1
if (grid[i][j] > 0)
{
for ( int k = 0; k < 8; k++)
{
if (save(grid, i + u[k],
j + v[k]) &&
grid[i + u[k]][j + v[k]] > 0)
{
// If initial value > 0,
// just increment it by 1
grid[i][j]++;
}
}
}
// IF the initial value
// of the grid(i, j) is 0
else
{
for ( int k = 0; k < 8; k++)
{
if (save(grid, i + u[k],
j + v[k]) &&
grid[i + u[k]][j + v[k]] > 0)
{
// If initial value <= 0
// just decrement it by 1
grid[i][j]--;
}
}
}
}
}
// Generating new Generation.
// Now the magnitude of the
// grid will represent number
// of neighbours
for ( int i = 0; i < p; i++)
{
for ( int j = 0; j < q; j++)
{
// If initial value was 1.
if (grid[i][j] > 0)
{
// Since Any live cell with
// < 2 live neighbors dies
if (grid[i][j] < 3)
grid[i][j] = 0;
// Since Any live cell with
// 2 or 3 live neighbors live
else if (grid[i][j] <= 4)
grid[i][j] = 1;
// Since Any live cell with
// > 3 live neighbors dies
else if (grid[i][j] > 4)
grid[i][j] = 0;
}
else
{
// Since Any dead cell with
// exactly 3 live neighbors
// becomes a live cell
if (grid[i][j] == -3)
grid[i][j] = 1;
else
grid[i][j] = 0;
}
}
}
} // Driver code int main ()
{ vector<vector< int >> grid = {{0, 0, 0, 0, 0,
0, 0, 0, 0, 0},
{0, 0, 0, 1, 1,
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}};
// Function to generate
// New Generation inplace
solve(grid);
// Displaying the grid
print(grid);
return 0;
} |
// Java program for // the above approach import java.util.*;
import java.lang.*;
class GFG{
static void print( int [][] grid)
{ int p = grid.length,
q = grid[ 0 ].length;
for ( int i = 0 ; i < p; i++)
{
for ( int j = 0 ; j < q; j++)
{
System.out.print(grid[i][j]);
}
System.out.println();;
}
} static boolean save( int [][] grid,
int row, int col)
{ return (grid.length > row &&
grid[ 0 ].length > col &&
row >= 0 && col >= 0 );
} static void solve( int [][] grid)
{ int p = grid.length,
q = grid[ 0 ].length;
// Possible neighboring
// indexes
int u[] = { 1 , - 1 , 0 , 1 ,
- 1 , 0 , 1 , - 1 };
int v[] = { 0 , 0 , - 1 , - 1 ,
- 1 , 1 , 1 , 1 };
for ( int i = 0 ; i < p; i++)
{
for ( int j = 0 ; j < q; j++)
{
// IF the initial value
// of the grid(i, j) is 1
if (grid[i][j] > 0 )
{
for ( int k = 0 ; k < 8 ; k++)
{
if (save(grid, i + u[k],
j + v[k]) &&
grid[i + u[k]][j + v[k]] > 0 )
{
// If initial value > 0,
// just increment it by 1
grid[i][j]++;
}
}
}
// IF the initial value
// of the grid(i, j) is 0
else
{
for ( int k = 0 ; k < 8 ; k++)
{
if (save(grid, i + u[k],
j + v[k]) &&
grid[i + u[k]][j + v[k]] > 0 )
{
// If initial value <= 0
// just decrement it by 1
grid[i][j]--;
}
}
}
}
}
// Generating new Generation.
// Now the magnitude of the
// grid will represent number
// of neighbours
for ( int i = 0 ; i < p; i++)
{
for ( int j = 0 ; j < q; j++)
{
// If initial value was 1.
if (grid[i][j] > 0 )
{
// Since Any live cell with
// < 2 live neighbors dies
if (grid[i][j] < 3 )
grid[i][j] = 0 ;
// Since Any live cell with
// 2 or 3 live neighbors live
else if (grid[i][j] <= 4 )
grid[i][j] = 1 ;
// Since Any live cell with
// > 3 live neighbors dies
else if (grid[i][j] > 4 )
grid[i][j] = 0 ;
}
else
{
// Since Any dead cell with
// exactly 3 live neighbors
// becomes a live cell
if (grid[i][j] == - 3 )
grid[i][j] = 1 ;
else
grid[i][j] = 0 ;
}
}
}
} // Driver code public static void main (String[] args)
{ int [][] grid = {{ 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 1 , 1 ,
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 }};
// Function to generate
// New Generation inplace
solve(grid);
// Displaying the grid
print(grid);
} } // This code is contributed by offbeat |
# Python3 implementation of # the above approach def print2dArr(grid):
p = len (grid)
q = len (grid[ 0 ])
for i in range (p):
for j in range (q):
print (grid[i][j], end = '')
print ()
# Function to check if # index are not out of grid def save(grid, row, col):
return ( len (grid) > row and len (grid[ 0 ]) > col and row > = 0 and col > = 0 )
# Function to get New Generation def solve(grid):
p = len (grid)
q = len (grid[ 0 ])
u = [ 1 , - 1 , 0 , 1 , - 1 , 0 , 1 , - 1 ]
v = [ 0 , 0 , - 1 , - 1 , - 1 , 1 , 1 , 1 ]
for i in range (p):
for j in range (q):
# IF the initial value
# of the grid(i, j) is 1
if (grid[i][j] > 0 ):
for k in range ( 8 ):
if (save(grid, i + u[k], j + v[k]) and grid[i + u[k]][j + v[k]] > 0 ):
# If initial value > 0,
# just increment it by 1
grid[i][j] + = 1
# IF the initial value
# of the grid(i, j) is 0
else :
for k in range ( 8 ):
if (save(grid, i + u[k], j + v[k]) and grid[i + u[k]][j + v[k]] > 0 ):
# If initial value <= 0
# just decrement it by 1
grid[i][j] - = 1
# Generating new Generation.
# Now the magnitude of the
# grid will represent number
# of neighbours
for i in range (p):
for j in range (q):
# If initial value was 1.
if (grid[i][j] > 0 ):
# Since Any live cell with
# < 2 live neighbors dies
if (grid[i][j] < 3 ):
grid[i][j] = 0
# Since Any live cell with
# 2 or 3 live neighbors live
elif (grid[i][j] < = 4 ):
grid[i][j] = 1
# Since Any live cell with
# > 3 live neighbors dies
elif (grid[i][j] > 4 ):
grid[i][j] = 0
else :
# Since Any dead cell with
# exactly 3 live neighbors
# becomes a live cell
if (grid[i][j] = = - 3 ):
grid[i][j] = 1
else :
grid[i][j] = 0
# Driver code if __name__ = = '__main__' :
grid = [[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ],
[ 0 , 0 , 0 , 1 , 1 , 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 , ], ]
# Function to generate
# New Generation inplace
solve(grid)
# Displaying the grid
print2dArr(grid)
|
// C# program for // the above approach using System;
using System.Text;
public class GFG{
static void print( int [,] grid)
{
int p = grid.GetLength(0), q = grid.GetLength(1);
for ( int i = 0; i < p; i++)
{
for ( int j = 0; j < q; j++)
{
Console.Write(grid[i,j]);
}
Console.Write( "\n" );
}
}
static bool save( int [,] grid, int row, int col)
{
return (grid.GetLength(0) > row && grid.GetLength(1) > col && row >= 0 && col >= 0);
}
static void solve( int [,] grid)
{
int p = grid.GetLength(0), q = grid.GetLength(1);
// Possible neighboring
// indexes
int [] u = {1, -1, 0, 1, -1, 0, 1, -1};
int [] v = {0, 0, -1, -1, -1, 1, 1, 1};
for ( int i = 0; i < p; i++)
{
for ( int j = 0; j < q; j++)
{
// IF the initial value
// of the grid(i, j) is 1
if (grid[i,j] > 0)
{
for ( int k = 0; k < 8; k++)
{
if (save(grid, i + u[k], j + v[k]) && grid[(i + u[k]),(j + v[k])] > 0)
{
// If initial value > 0,
// just increment it by 1
grid[i,j]++;
}
}
}
// IF the initial value
// of the grid(i, j) is 0
else
{
for ( int k = 0; k < 8; k++)
{
if (save(grid, i + u[k], j + v[k]) && grid[(i + u[k]),(j + v[k])] > 0)
{
// If initial value <= 0
// just decrement it by 1
grid[i,j]--;
}
}
}
}
}
// Generating new Generation.
// Now the magnitude of the
// grid will represent number
// of neighbours
for ( int i = 0; i < p; i++)
{
for ( int j = 0; j < q; j++)
{
// If initial value was 1.
if (grid[i,j] > 0)
{
// Since Any live cell with
// < 2 live neighbors dies
if (grid[i,j] < 3)
grid[i,j] = 0;
// Since Any live cell with
// 2 or 3 live neighbors live
else if (grid[i,j] <= 4)
grid[i,j] = 1;
// Since Any live cell with
// > 3 live neighbors dies
else if (grid[i,j] > 4)
grid[i,j] = 0;
}
else
{
// Since Any dead cell with
// exactly 3 live neighbors
// becomes a live cell
if (grid[i,j] == -3)
grid[i,j] = 1;
else
grid[i,j] = 0;
}
}
}
}
//Driver Code
static public void Main (){
int [,] grid = {{0, 0, 0, 0, 0,
0, 0, 0, 0, 0},
{0, 0, 0, 1, 1,
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}};
// Function to generate
// New Generation inplace
solve(grid);
// Displaying the grid
print(grid);
}
} // This code is contributed by shruti456rawal |
<script> // JavaScript implementation of // the above approach function print2dArr(grid){
let p = grid.length
let q = grid[0].length
for (let i=0;i<p;i++){
for (let j=0;j<q;j++){
document.write(grid[i][j], '' )
}
document.write( "</br>" )
}
} // Function to check if // index are not out of grid function save(grid, row, col){
return grid.length > row && grid[0].length > col && row >= 0 && col >= 0
} // Function to get New Generation function solve(grid){
let p = grid.length
let q = grid[0].length
let u = [1, -1, 0, 1, -1, 0, 1, -1]
let v = [0, 0, -1, -1, -1, 1, 1, 1]
for (let i = 0; i < p; i++)
{
for (let j = 0; j < q; j++)
{
// IF the initial value
// of the grid(i, j) is 1
if (grid[i][j] > 0)
{
for (let k = 0; k < 8; k++)
{
if (save(grid, i + u[k], j + v[k]) && grid[i + u[k]][j + v[k]] > 0)
// If initial value > 0,
// just increment it by 1
grid[i][j] += 1
}
}
// IF the initial value
// of the grid(i, j) is 0
else {
for (let k = 0;k<8;k++){
if (save(grid, i + u[k], j + v[k]) && grid[i + u[k]][j + v[k]] > 0)
// If initial value <= 0
// just decrement it by 1
grid[i][j] -= 1
}
}
}
}
// Generating new Generation.
// Now the magnitude of the
// grid will represent number
// of neighbours
for (let i = 0; i < p; i++)
{
for (let j = 0; j < q; j++)
{
// If initial value was 1.
if (grid[i][j] > 0){
// Since Any live cell with
// < 2 live neighbors dies
if (grid[i][j] < 3)
grid[i][j] = 0
// Since Any live cell with
// 2 or 3 live neighbors live
else if (grid[i][j] <= 4)
grid[i][j] = 1
// Since Any live cell with
// > 3 live neighbors dies
else if (grid[i][j] > 4)
grid[i][j] = 0
}
else {
// Since Any dead cell with
// exactly 3 live neighbors
// becomes a live cell
if (grid[i][j] == -3)
grid[i][j] = 1
else
grid[i][j] = 0
}
}
}
} // Driver code let grid = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], [0, 0, 0, 1, 1, 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, ], ]
// Function to generate // New Generation inplace solve(grid) // Displaying the grid print2dArr(grid) // This code is contributed by shinjanpatra </script> |
0000000000 0001100000 0001100000 0000000000 0000000000
Time complexity: O(N*M)
Auxiliary Space: O(1)