Algorithm / / 2025. 3. 2. 01:26

[15685] 드래곤 커브 리뷰 및 코드 개선

1. 문제 개요

 

백준 15685번 - 드래곤 커브는 좌표 평면 위에서 드래곤 커브를 그리고, 1×1 정사각형이 몇 개나 만들어지는지 세는 문제입니다.

드래곤 커브는 초기 선분을 기준으로 90도 회전하며 확장되는 방식으로 그려집니다. 여러 개의 드래곤 커브가 그려진 후, 네 꼭짓점이 모두 포함된 1×1 정사각형의 개수를 구하는 것이 목표입니다.


2. 기존 코드 분석

 

다음은 기존 코드입니다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static int[][] grid = new int[102][102];
    static int[] DY = {0, -1, 0, 1};
    static int[] DX = {1, 0, -1, 0};
    static int result = 0;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int[][] matrix = new int[N][];
        for (int i = 0; i < N; i++)
            matrix[i] = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        for (int[] loc : matrix) {
            List<Integer> route = new ArrayList<>();
            dragonRun(loc[1], loc[0], loc[2], loc[3], route);
        }
        System.out.println(result);
    }

    private static void check(int y, int x) {
        if ((grid[y][x] & 1) == 0) {
            if ((grid[y][x] |= 1) == 15)
                result++;
        }
        if ((grid[y][x+1] & 2) == 0) {
            if ((grid[y][x+1] |= 2) == 15)
                result++;
        }
        if ((grid[y+1][x] & 4) == 0) {
            if ((grid[y+1][x] |= 4) == 15)
                result++;
        }
        if ((grid[y+1][x+1] & 8) == 0) {
            if ((grid[y+1][x+1] |= 8) == 15)
                result++;
        }
    }

    private static void dragonRun(int starty, int startx, int direction, int level, List<Integer> route) {
        int d = direction;
        int y = starty;
        int x = startx;
        check(y,x);
        y += DY[d];
        x += DX[d];
        check(y,x);
        route.add(d);

        for (int t = 1; t <= level; t++) {
            for (int i = route.size() - 1; i >= 0; i--) {
                d = (route.get(i) + 1) % 4;
                y += DY[d];
                x += DX[d];
                route.add(d);
                check(y,x);
            }
        }
    }
}

 

기존 코드의 문제점

  1. 가독성이 낮음
    • check() 메서드가 비트 연산을 사용하여 네 꼭짓점의 상태를 관리하는데, 코드만 보고 어떤 동작을 하는지 바로 이해하기 어려움.
    • dragonRun()에서 방향과 위치를 관리하는 로직이 직관적이지 않음.
  2. 책임 분리 부족
    • 드래곤 커브를 생성하면서 동시에 정사각형 개수를 세는 로직이 섞여 있음.
    • 개별적인 기능을 분리하면 유지보수성이 향상될 것.


 

3. 개선 코드

 

아래는 기존 코드를 가독성과 유지보수성을 고려하여 개선한 코드입니다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static final int SIZE = 101;
    static boolean[][] grid = new boolean[SIZE + 1][SIZE + 1];
    static final int[] DX = {1, 0, -1, 0};
    static final int[] DY = {0, -1, 0, 1};

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());

        for (int i = 0; i < N; i++) {
            String[] tokens = br.readLine().split(" ");
            int x = Integer.parseInt(tokens[0]);
            int y = Integer.parseInt(tokens[1]);
            int d = Integer.parseInt(tokens[2]);
            int g = Integer.parseInt(tokens[3]);

            drawDragonCurve(x, y, d, g);
        }

        System.out.println(countCompleteSquares());
    }

    private static void drawDragonCurve(int x, int y, int d, int g) {
        List<Integer> directions = new ArrayList<>();
        directions.add(d);
        grid[y][x] = true;
        int nx = x + DX[d];
        int ny = y + DY[d];
        grid[ny][nx] = true;

        for (int gen = 1; gen <= g; gen++) {
            for (int i = directions.size() - 1; i >= 0; i--) {
                int newDir = (directions.get(i) + 1) % 4;
                nx += DX[newDir];
                ny += DY[newDir];
                grid[ny][nx] = true;
                directions.add(newDir);
            }
        }
    }

    private static int countCompleteSquares() {
        int count = 0;
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                if (grid[i][j] && grid[i][j+1] && grid[i+1][j] && grid[i+1][j+1]) {
                    count++;
                }
            }
        }
        return count;
    }
}

 

개선된 코드의 장점

  1. 가독성 향상: 비트 마스크 없이, 단순한 boolean 배열을 사용하여 논리를 명확하게 표현.
  2. 책임 분리: 드래곤 커브 생성과 정사각형 카운트를 별도 메서드로 분리.
  3. 유지보수성 증가: 코드 구조가 단순하여 추가 수정이 용이.


 

4. 마무리

이제 개선된 코드로 더 쉽게 문제를 이해하고 유지보수할 수 있는 구조를 갖추었습니다. 비슷한 문제를 풀 때도 책임 분리, 가독성 개선을 염두에 두고 작성하면 좋은 코드 품질을 유지할 수 있습니다! 🚀

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유