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);
}
}
}
}
기존 코드의 문제점
- 가독성이 낮음
- check() 메서드가 비트 연산을 사용하여 네 꼭짓점의 상태를 관리하는데, 코드만 보고 어떤 동작을 하는지 바로 이해하기 어려움.
- dragonRun()에서 방향과 위치를 관리하는 로직이 직관적이지 않음.
- 책임 분리 부족
- 드래곤 커브를 생성하면서 동시에 정사각형 개수를 세는 로직이 섞여 있음.
- 개별적인 기능을 분리하면 유지보수성이 향상될 것.
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;
}
}
개선된 코드의 장점
- 가독성 향상: 비트 마스크 없이, 단순한 boolean 배열을 사용하여 논리를 명확하게 표현.
- 책임 분리: 드래곤 커브 생성과 정사각형 카운트를 별도 메서드로 분리.
- 유지보수성 증가: 코드 구조가 단순하여 추가 수정이 용이.
4. 마무리
이제 개선된 코드로 더 쉽게 문제를 이해하고 유지보수할 수 있는 구조를 갖추었습니다. 비슷한 문제를 풀 때도 책임 분리, 가독성 개선을 염두에 두고 작성하면 좋은 코드 품질을 유지할 수 있습니다! 🚀
'Algorithm' 카테고리의 다른 글
[13460] 구슬 탈출 2 문제 리뷰 및 코드 개선 (0) | 2025.03.04 |
---|---|
[5373] 큐빙 문제 리뷰 및 코드 개선 [미해결] (0) | 2025.03.03 |
[15683] 감시 문제 리뷰 및 코드 개선 (0) | 2025.03.03 |
[15686] 치킨 배달 문제 리뷰 및 개선 (1) | 2025.03.02 |
[15684] 사다리 조작 리뷰 및 코드 개선 (0) | 2025.03.02 |