판화
문제
W대학교 미술대학 조소과에서는 지루한 목판화 작업을 하는 학생들을 돕기 위해 판화 기계를 제작하였다.
기계는 로봇 팔이 쥔 조각도를 상하좌우 네 방향으로 움직일 수 있는 구조로서, 조각도 아래에 목판을 놓으면 그 위에 선들을 자동으로 그어주는 기능을 가지고 있다.
목판에는 N2개의 점들이 일정한 간격으로 N행 N열의 격자모양을 이루며 찍혀있다. 처음 로봇의 조각도를 올려놓는 위치는 항상 이 점들 중 맨 왼쪽 맨 위의 꼭짓점이다.
로봇 팔을 움직이는 명령의 순서가 주어졌을 때, 목판 위에 패인 조각도의 혼적을 출력하는 프로그램을 작성하시오.
판화 기계는 작동 도중 로봇 팔이 격자 바깥으로 나가도록 하는 움직임 명령을 만나면, 무시하고 그 다음 명령을 진행한다.
입력
첫째 줄에 목판의 크기 N (2 ≤ N ≤ 10)이 주어진다. 행 열의 점들이 찍혀 있다는 의미이다. 둘째 줄에 로봇팔의 움직임이 한 줄로 공백 없이 입력된다. 위쪽으로 이동은 'U', 아래쪽으로 이동은 'D', 왼쪽으로 이동은 'L', 오른쪽으로 이동은 'R'로 표시된다. 로봇팔의 움직임을 나타내는 이 문자열의 길이는 최대 250이다.
출력
로봇팔이 지나지 않은 점은 '.'으로, 로봇팔이 수직 방향으로만 지난 점은 '|'으로, 로봇팔이 수평 방향으로만 지난 점은 '-'으로, 수직과 수평 방향 모두로 지난 점은 '+'로 표기하도록 한다. 네 문자의 ASCII 코드는 각각 46, 124, 45, 43이다.
예제 입력 1
5
DRDRRUU
예제 출력 1
|..|.
++.|.
.+-+.
.....
.....
예제 입력 2
4
RRRDDDDULL
예제 출력 2
---+
...|
.--+
...|
예제 입력 3
5
RRDDLLUURRDDLLUUR
예제 출력 3
+-+..
|.|..
+-+..
.....
.....
이거를 처음에는 그냥 말 그대로 구현했다.
요즘 문제풀이 경향은
1) main()에는 흐름만 보이도록 하고 나머지 기능은 전부 메서드로 뽑아버리기
2) 구현하는 데 사용하는 변수 구조가 복잡한 경우 일일이 각각의 변수로 선언하지 않고 객체 자료형 직접 만들어서 field로 불러 쓰기
정도인데 main() 안에 몇십 줄 쓰는 것보다 코드 구조가 잘 잡히는 것 같아서 만족스럽다. 다른 사람이 보기엔 어떨지 모르겠는데 ㅋㅋㅋㅋ
import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;
public class BOJ_1730 {
static int size; // board size
static char[] orderLine;
static char[][] board; // 그림을 그릴 board
static boolean stop; // orderLine이 없는 경우 true
// Move는 방향에 따른 좌표 변화값(x, y)과 판때기(?)에 그릴 값(c)을 저장함
// 탐색 중인 현재 위치 인덱스를 저장하는 변수 curr로도 사용됨
static class Move{
int x, y;
char c;
private Move(int y, int x, char c) { // 파라메터 순서 유의. y == row / x == col
this.x = x;
this.y = y;
this.c = c;
}
}
public static void main(String[] args) {
set();
activate();
draw();
}
static void set() {
Scanner sc = new Scanner(System.in);
size = sc.nextInt();
board = new char[size][size];
for(char[] ard : board) {
Arrays.fill(ard, '.');
}
sc.nextLine(); // 개행 제거, order 없는 경우까지 케어
String order = sc.nextLine();
if(order.isEmpty()) { // 들어온 order가 없는 경우 바로 print해야 한다.
stop = true;
return;
}
orderLine = new char[order.length()];
for(int i = 0; i<order.length(); i++) {
orderLine[i] = order.charAt(i);
}
}
static void activate() { // 기계 작동시키기
if(stop) return; // 이 조건은 activate()에 있어도 되고 main()에 있어도 된다
HashMap<Character, Move> controller = new HashMap<Character, Move>();
controller.put('D', new Move(0, 1, '|'));
controller.put('U', new Move(0, -1, '|'));
controller.put('L', new Move(-1, 0, '-'));
controller.put('R', new Move(1, 0, '-'));
// 'D', 'U' 는 수직 방향 이동이다.
// 'L', 'R' 은 수평 방향 이동이다.
Move curr = new Move(0, 0, '$'); // '$'은 객체 생성 위해 임의 부여된 char(사용되지 않음)
for(char i : orderLine) {
Move now = controller.get(i);
// java.lang.ArrayIndexOutOfBoundsException 방지(문제 본문에 해당 exception 발생할 수 있다고 명시됨)
if(curr.x+now.x >= size || curr.x+now.x < 0 || curr.y+now.y >= size || curr.y+now.y < 0) continue;
// 기계가 작동하기 시작하면 '현재 위치'와 '이동한 위치'에 모두 그림을 그린다.
// 현재 위치에 그리기
if(board[curr.x][curr.y] != '.' && board[curr.x][curr.y] != now.c) board[curr.x][curr.y] = '+';
else board[curr.x][curr.y] = now.c;
// 이동하기
curr.x = curr.x+now.x;
curr.y = curr.y+now.y;
// 이동한 위치에 그리기
if(board[curr.x][curr.y] != '.' && board[curr.x][curr.y] != now.c) board[curr.x][curr.y] = '+';
else board[curr.x][curr.y] = now.c;
}
}
static void draw() { // 그린 그림 출력하기
for(char[] ard : board) {
for(char bo : ard) {
System.out.print(bo);
}
System.out.println();
}
}
}
64, 70번 라인(if / else 연달아 쓰이는 부분)이 같은 로직 반복이라 좀 껄쩍지근했는데
두 줄 짜리를 함수로 따로 빼기도 뭐하고
아득바득 줄이기엔 가독성 떨어질 것 같아서 그냥 두었다.
처음에 제출했을 때 쭈욱 채점 잘 되다가 갑자기 끝판에 NoSuchElementException이 나면서 비정상 종료됐는데
저게 왜 저럴까? 싶어서 생각해 보니
TC에 order가 없는 경우가 있다. (TC에서 방향 문자열이 없고 배열 사이즈만 주는 경우)
그리고 나는 Scanner를 쓰면서 sc.nextInt()로 size를 받고 sc.next()로 방향 문자열을 입력받고 있었기 때문에
개행 문자가 계속 들어와도 케이스가 없다는 걸 인지하지 못해서 Exception이 터짐.
이런 경우가 있기 때문에 가급적이면 nextLine()을 쓰려고 한다.
sc.next()를 sc.nextLine()으로 고쳐서(+sc.nextLine()을 한 번 더 써서 nextInt() 이후에 남은 개행문자를 날려야 함) 해결.
그리고 이 문제는 비트연산으로도 풀 수 있는데
그건 지금 풀어보는 중임
'2024-?학기 ??? > Solving' 카테고리의 다른 글
BOJ 11005_진법 변환 2 (0) | 2024.06.21 |
---|---|
BOJ 10448_유레카 이론 (0) | 2024.06.21 |
BOJ 3085_사탕 게임 (0) | 2024.06.11 |
BOJ 2309_일곱 난쟁이 (0) | 2024.06.03 |
PGMRS_가장 많이 받은 선물(카카오 2024) (1) | 2024.04.18 |
댓글