오랜만에 JavaPS(테트로미노 (백준 14500번))를 해봤다.

클린 코드, TDD에 대한 내용을 여기저기서 조금씩이라도 습득하면서 신경을 쓰면서 하니까 확실히 이전보다는 메서드 분리 횟수가 많아진 것 같다.

조금 고민이 되는 점은.. 클린 코드에서는 들여쓰기 1번 만으로 구현이 가능해야 한다는 내용도 있는데, while 문 내에서 특정 조건일 때 continue 시키는 경우도 가능한지 궁금하다. 좀 더 많은 내용을 보고 학습하면 이렇게 애매한 부분들도 채워지지 않을까?


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;

public class Main {

    static int answer = 0;
    static final int[] dy = {0, 1, 0, -1};
    static final int[] dx = {1, 0, -1, 0};
    static int N;
    static int M;
    static int[][] nodeMap;
    static Deque<TetromioPart> deque = new ArrayDeque();

    public static void main(String[] args) {
        inputAndInitialize();
        bfs();
        System.out.println(answer);
    }

    static void bfs() {
        int y = 0;
        int x = 0;
        int beforeDirection = -1;
        int cnt = 0;
        int price = 0;
        int ny = 0;
        int nx = 0;

        while (!deque.isEmpty()) {
            TetromioPart tetromioPart = deque.pop();
            y = tetromioPart.y;
            x = tetromioPart.x;
            beforeDirection = tetromioPart.beforeDirection;
            cnt = tetromioPart.cnt;
            price = tetromioPart.price;
            if (cnt == 4) {
                updateAnswer(price);
                continue;
            }

            for (int i = 0; i < 4; i++) {
                if (i == beforeDirection) continue;
                ny = y + dy[i];
                nx = x + dx[i];
                if (!isInboundary(ny, nx)) {
                    continue;
                }
                
                deque.add(
                    new TetromioPart(ny, nx, i, cnt+1, price+nodeMap[ny][nx])
                );
            }
        }
    }

    static void updateAnswer(int price) {
        if (answer < price) {
            answer = price;
        }
    }

    static void sumArround(int y, int x) {
        int sum = nodeMap[y][x];

        for (int i = 0; i < 4; i++) {
            sum = nodeMap[y][x];
            for (int j = 0; j < 4; j++) {
                if (i == j) continue;
                sum += nodeMap[y+dy[j]][x+dx[j]];
            }
            updateAnswer(sum);
        }
        
        
    }

    static boolean isInboundary(int y, int x) {
        if (y >= 1 && y < N+1 && x >= 1 && x < M+1) return true;
        return false; 
    }

    static void inputAndInitialize() {
        Reader reader = new Reader();
        N = reader.readInt();
        M = reader.readInt();
        nodeMap = new int[N+2][M+2];
        for (int i = 1; i < N+1; i++) {
            for (int j = 1; j < M+1; j++) {
                int price = reader.readInt();
                nodeMap[i][j] = price;
                sumArround(i, j);
                deque.add(new TetromioPart(i, j, -3, 1, price));
            }
        }

        for (int i = 1; i < N+1; i++) {
            for (int j = 1; j < M+1; j++) {
                sumArround(i, j);
            }
        }
    }

    static class Reader {
        BufferedReader bufferedReader;
        StringTokenizer stringTokenizer;
        
        Reader (){
            bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        }

        String read() {
            while (stringTokenizer == null || !stringTokenizer.hasMoreElements()) {
                try {
                    stringTokenizer = new StringTokenizer(bufferedReader.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return stringTokenizer.nextToken();
        }

        int readInt() {
            return Integer.parseInt(read());
        }
    }

    static class TetromioPart {
        int y;
        int x;
        int beforeDirection;
        int cnt;
        int price;
        
        TetromioPart(int y, int x, int nextDirection, int cnt, int price) {
            this.y = y;
            this.x = x;
            this.beforeDirection = (nextDirection + 2) % 4;
            this.cnt = cnt;
            this.price = price;
        }
    }
}