Game of Life: Next Generation

medium Matrix (2D arrays)

Problem

The matrix has live cells (1) and dead cells (0). A cell has up to 8 neighbours (also diagonal). A live cell with 2 or 3 live neighbours stays alive, otherwise it dies. A dead cell with exactly 3 live neighbours becomes alive. All cells change at the same time. Print the next generation. Cells outside the matrix are dead.

Constraints

  • 1 <= r, c <= 100
  • cells are 0 or 1

Examples

Input

3 3
0 1 0
0 1 0
0 1 0

Output

0 0 0
1 1 1
0 0 0

Solutions

Best approachTime O(r * c)Space O(r * c)

If you change cells while you scan, later cells see the new values and the result is wrong. A second matrix (or encoding old and new states in one number) keeps the generation change simultaneous.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process a matrix.
 * Input   : r and c, then r rows of c integers.
 * Output  : The next generation.
 * Approach: Count neighbours.
 * Time    : O(r * c)
 * Space   : O(r * c)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(int[][] m) {
        int rows = m.length;
        int cols = m[0].length;

        // Step 1: Write the new generation in a second matrix. All cells must be computed from the OLD generation.
        int[][] next = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                // Step 2: Count the live neighbours. The cell itself is skipped. Cells outside the matrix count as dead.
                int neighbours = 0;
                for (int x = i - 1; x <= i + 1; x++) {
                    for (int y = j - 1; y <= j + 1; y++) {
                        if ((x != i || y != j) && x >= 0 && x < rows && y >= 0 && y < cols) {
                            neighbours += m[x][y];
                        }
                    }
                }

                // Step 3: Apply the rules.
                if (m[i][j] == 1) {
                    next[i][j] = neighbours == 2 || neighbours == 3 ? 1 : 0;
                } else {
                    next[i][j] = neighbours == 3 ? 1 : 0;
                }
            }
        }

        String[] output = new String[rows];
        for (int i = 0; i < rows; i++) {
            StringBuilder row = new StringBuilder();
            for (int j = 0; j < cols; j++) {
                row.append(j == 0 ? "" : " ").append(next[i][j]);
            }
            output[i] = row.toString();
        }
        return output;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int rows = scanner.nextInt();
        int cols = scanner.nextInt();
        int[][] m = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                m[i][j] = scanner.nextInt();
            }
        }
        System.out.println(String.join("\n", solve(m)));
    }
}
Hints (1)
  1. Why do we need a second matrix?