diff --git a/java/magic-squares-in-grid.java b/java/magic-squares-in-grid.java new file mode 100644 index 0000000..e5e54dd --- /dev/null +++ b/java/magic-squares-in-grid.java @@ -0,0 +1,68 @@ +class Solution { + private static final int SQUARE_SIZE = 3; + + private int sum(int[][] grid, int y, int x, int dy, int dx) { + int total = 0; + for (int d = 0; d < SQUARE_SIZE; ++d) { + total += grid[y + d * dy][x + d * dx]; + } + return total; + } + + private static final int ALL_DIGITS = (~(((~0) >> 9) << 9)); + + private boolean isMagicSquare(int[][] grid, int y, int x) { + // check the digits + int seen = 0; + for (int d = 0; d < SQUARE_SIZE * SQUARE_SIZE; ++d) { + int dy = d / SQUARE_SIZE, dx = d % SQUARE_SIZE; + + int digit = grid[y + dy][x + dx]; + if (digit < 1 || digit > 9) { + // out of range + return false; + } + + seen |= 1 << (digit - 1); + } + + if (seen != ALL_DIGITS) { + // repeated digits + return false; + } + + // check the sums + int expectedSum = sum(grid, y, x, 1, 1); + int diag2 = sum(grid, y, x + 2, 1, -1); + if (diag2 != expectedSum) { + // diagonals are broken + return false; + } + + for (int d = 0; d < SQUARE_SIZE; ++d) { + if (sum(grid, y + d, x, 0, 1) != expectedSum) { + return false; + } + + if (sum(grid, y, x + d, 1, 0) != expectedSum) { + return false; + } + } + + return true; + } + + public int numMagicSquaresInside(int[][] grid) { + int squares = 0; + + for (int y = 0; y + 2 < grid.length; ++y) { + for (int x = 0; x + 2 < grid[y].length; ++x) { + if (isMagicSquare(grid, y, x)) { + ++squares; + } + } + } + + return squares; + } +}