방학을 맞아 코딩 테스트 준비를 할겸 알고리즘 문제 풀이를 시작해보려고 한다.
기존에는 백준은 파이썬, 프로그래머스는 자바로 풀었었는데 앞으로는 자바로만 풀어볼 예정이다!
우선, 백준에서는 삼성 SW 역량 테스트 기출 문제집을 풀어보고, 프로그래머스에서는 기존에 풀었던 Level1 문제 중 새로 추가된 문제를 다 풀고 Level2로 넘어갈 예정이다.
오늘은 백준 문제를 먼저 풀어보았는데 백준에서 자바로 문제를 푼 것은 처음이었기 때문에 제출하는 형식을 찾아보았더니, 나름의 규칙이 있었다. 해당 내용은 포스팅 제일 아래에 써 두었다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws Exception {
rollTheDice();
}
// 주사위 굴리기
public static void rollTheDice() throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken()); // 지도의 세로 크기
int M = Integer.parseInt(st.nextToken()); // 지도의 가로 크기
int y = Integer.parseInt(st.nextToken()); // 주사위를 놓은 곳의 y 좌표
int x = Integer.parseInt(st.nextToken()); // 주사위를 놓은 곳의 x 좌표
int K = Integer.parseInt(st.nextToken()); // 명령의 개수
int[] dice = new int[6]; // 주사위
int[][] map = new int[N][M]; // 지도
// 입력 값에 따라 지도에 숫자 넣기
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int l = 0; l < M; l++) {
int a = Integer.parseInt(st.nextToken());
map[i][l] = a;
}
}
st = new StringTokenizer(br.readLine());
int move;
int[] hor = {0, 3, 5, 2}; // 주사위의 가로 라인 1 4 6 3
int[] ver = {0, 1, 5, 4}; // 주사위의 세로 라인 1 2 6 5
// 명령 개수 만큼 반복문 실행
for (int j = 0; j < K; j++) {
move = Integer.parseInt(st.nextToken()); // 1: 동쪽, 2: 서쪽, 3: 북쪽, 4: 남쪽
boolean tag = true; // 지도에서 벗어나는 명령인지 판별하기 위한 bool 변수
switch (move) {
case 1:
x += 1;
// 지도에서 벗어나는 경우 x를 원래대로 돌리고, tag를 false로 변경
if (x >= M) {
x -= 1;
tag = false;
}
// 그렇지 않은 경우는, 주사위의 가로 라인 값들을 동쪽으로 한 칸씩 밀기
else {
int temp = dice[0];
for (int k = 0; k < 3; k++) {
dice[hor[k]] = dice[hor[k + 1]];
}
dice[2] = temp;
}
break;
case 2:
x -= 1;
if (x < 0) {
x += 1;
tag = false;
} else {
int temp = dice[2];
for (int k = 3; k > 0; k--) {
dice[hor[k]] = dice[hor[k - 1]];
}
dice[0] = temp;
}
break;
case 3:
y -= 1;
if (y < 0) {
y += 1;
tag = false;
} else {
int temp = dice[0];
for (int k = 0; k < 3; k++) {
dice[ver[k]] = dice[ver[k + 1]];
}
dice[4] = temp;
}
break;
case 4:
y += 1;
if (y >= N) {
y -= 1;
tag = false;
} else {
int temp = dice[4];
for (int k = 3; k > 0; k--) {
dice[ver[k]] = dice[ver[k - 1]];
}
dice[0] = temp;
}
break;
}
// tag가 true인 경우
if (tag) {
// 주사위가 놓여진 칸의 숫자가 0이 아니면, 주사위의 아랫면에 칸의 숫자를 대입하고, 칸은 0으로 변경
if (map[y][x] != 0) {
dice[5] = map[y][x];
map[y][x] = 0;
}
// 주사위가 놓여진 칸의 숫자가 0이면, 칸에 주사위의 아랫면의 숫자를 대입
else {
map[y][x] = dice[5];
}
System.out.println(dice[0]); // 주사위의 윗면 출력
}
}
br.close();
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws Exception {
rollTheDice();
}
}
백준 알고리즘을 Java로 제출할 때는 위 코드처럼 클래스를 패키지 없이 Main으로 설정해야 된다고 한다.
시간 초과 시에는 본인이 사용한 입·출력 방법을 먼저 확인해 보자.
다음 링크에서 백준에서 제시하는 언어별 입력 속도 비교표와 출력 속도 비교표를 확인할 수 있다.
자바에서 표준 입력을 위해 사용하는 Scanner와 BufferedReader의 속도 차이가 꽤 큰 것을 확인할 수 있다. 표준 출력 역시 println과 BufferedWriter의 속도 차이가 엄청 크다!
추가로, 1 3 4 5와 같은 한줄 입력을 split()으로 나누는 것 보다 StringTokenizer로 나누는 것이 더 빠르니 사용할 때 고려해보자.