| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import static java.util.Arrays.copyOfRange;
- import static java.util.Arrays.stream;
-
- final class RectangleCounter {
-
- int countRectangles(final String[] rawGrid) {
- final int nRows = rawGrid.length;
- if (nRows == 0) return 0;
-
- final int nCols = rawGrid[0].length();
- if (nCols == 0) return 0;
-
- return new Grid(nRows, nCols, rawGrid).countRectangles();
- }
-
- private static final class Grid {
-
- private enum Tile {
- CORNER,
- HORIZONTAL_WALL,
- VERTICAL_WALL,
- SPACE;
-
- private static Tile fromChar(final char rawGridTile) {
- switch (rawGridTile) {
- case '+': return CORNER;
- case '-': return HORIZONTAL_WALL;
- case '|': return VERTICAL_WALL;
- case ' ': return SPACE;
- default: throw new IllegalStateException("Grid tile " + rawGridTile + " not recognized.");
- }
- }
-
- private boolean isHorizontalConnector() {
- return this == CORNER || this == HORIZONTAL_WALL;
- }
-
- private boolean isVerticalConnector() {
- return this == CORNER || this == VERTICAL_WALL;
- }
- }
-
- private int nRows, nCols;
- private final Tile[][] tiles;
-
- private Grid(final int nRows, final int nCols, final String[] rawGrid) {
- this.nRows = nRows;
- this.nCols = nCols;
- this.tiles = new Tile[nRows][nCols];
-
- for (int nRow = 0; nRow < nRows; nRow++) {
- for (int nCol = 0; nCol < nCols; nCol++) {
- tiles[nRow][nCol] = Tile.fromChar(rawGrid[nRow].charAt(nCol));
- }
- }
- }
-
- private int countRectangles() {
- int result = 0;
-
- for (int topRow = 0; topRow < nRows - 1; topRow++) {
-
- for (int leftCol = 0; leftCol < nCols - 1; leftCol++) {
-
- // Only check rectangles that lie below/to the right of our current coordinate:
- for (int bottomRow = topRow + 1; bottomRow < nRows; bottomRow++) {
-
- for (int rightCol = leftCol + 1; rightCol < nCols; rightCol++) {
-
- if (formsRectangle(topRow, bottomRow, leftCol, rightCol)) {
- result++;
- }
- }
- }
- }
- }
-
- return result;
- }
-
- private boolean formsRectangle(
- final int topRow,
- final int bottomRow,
- final int leftCol,
- final int rightCol) {
-
- return tiles[topRow][leftCol].equals(Tile.CORNER)
- && tiles[topRow][rightCol].equals(Tile.CORNER)
- && tiles[bottomRow][leftCol].equals(Tile.CORNER)
- && tiles[bottomRow][rightCol].equals(Tile.CORNER)
- && isHorizontalLineSegment(topRow, leftCol, rightCol)
- && isHorizontalLineSegment(bottomRow, leftCol, rightCol)
- && isVerticalLineSegment(leftCol, topRow, bottomRow)
- && isVerticalLineSegment(rightCol, topRow, bottomRow);
- }
-
- private boolean isHorizontalLineSegment(final int row, final int leftCol, final int rightCol) {
- return stream(copyOfRange(getRow(row), leftCol, rightCol))
- .allMatch(Tile::isHorizontalConnector);
- }
-
- private boolean isVerticalLineSegment(final int col, final int topRow, final int bottomRow) {
- return stream(copyOfRange(getCol(col), topRow, bottomRow))
- .allMatch(Tile::isVerticalConnector);
- }
-
- private Tile[] getRow(final int number) {
- return tiles[number];
- }
-
- private Tile[] getCol(final int number) {
- final Tile[] result = new Tile[nRows];
-
- for (int nRow = 0; nRow < nRows; nRow++) {
- result[nRow] = tiles[nRow][number];
- }
-
- return result;
- }
-
- }
-
- }
|