https://www.acmicpc.net/problem/2714
규현이는 승환이에게 사랑을 담은 문자 메시지를 자주 보낸다. 이것을 남에게 보이기 싫었던 규현이는 승환이와 비밀 규칙을 만들었다.
규현이는 비밀 메시지를 만들기 위한 행렬의 행의 수 R과 열의 수 C를 정했다. 그 다음 다음과 같은 규칙으로 비밀 메시지를 만든다.
먼저 규현이는 문자를 위 규칙을 이용해 글자를 숫자로 바꾼 다음에 이것은 5자리 이진수로 바꾼다. 그 다음 아래 그림과 같이 소용돌이 패턴으로 행렬에 채운다. 행렬의 모든 칸을 채우지 못할 때는, 0으로 계속 채운다. 예를 들어 규현이가 보내려는 메시지가 "ACM"이고, R=4, C=4로 정했다면, 다음과 같이 행렬을 채우면 된다.
A = 00001, C = 00011, M = 01101, 모자라는 칸은 0으로 채운다.
그 다음 행렬을 행 우선으로 읽은 뒤 (Row Major Order)에 승환이에게 보낸다.
위의 예시를 메시지로 보낸다면 0000110100101100이 된다.
승환이가 받은 비밀 메시지와 R과 C가 주어졌을 때, 이를 규현이가 보낸 문자 메시지로 변환하는 프로그램을 작성하시오.
첫째 줄에 테스트 케이스의 개수 T가 주어진다. (1 ≤ T ≤ 1,000) 각 테스트 케이스는 한 줄로 이루어져 있고, R, 공백, C, 공백, 승환이가 받은 메시지로 이루어져 있다. (1 ≤ R, C ≤ 21) 메시지는 0과 1로만 이루어져 있고, 이 길이는 항상 R*C이다.
각 테스트 케이스에 대해 규현이가 보내려고 변환되기 전 문자 메시지를 출력한다. 이때, 원래 문자 메시지가 공백으로 끝난다면, 그 공백을 모두 제거한 뒤에 출력한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int N = Integer.parseInt(bf.readLine());
while (N > 0) {
st = new StringTokenizer(bf.readLine());
int R = Integer.parseInt(st.nextToken());
int C = Integer.parseInt(st.nextToken());
String binary_num = st.nextToken();
int r = R;
int c = C;
//2차원 배열 형태로 한 글자씩 입력받아 입력받아 저장할 matrix
String[][] matrix = new String[R][C];
int k = 0;
int tmp = 1;
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
matrix[i][j] = binary_num.substring(k++, tmp++);
}
}
//소용돌이 형태로 이진수를 저장할 words 배열
String[] words = new String[R * C];
int index = 0;
int x = 0;
int y = 0;
R--;
int flag=1;
while (index < words.length) {
for (int i = 0; i < C; i++) {
words[index++] = matrix[x][y];
y+=flag;
}
x+=flag;
y+=flag*-1;
C--;
if (index>=words.length)
break;
for (int i = 0; i < R; i++) {
words[index++] = matrix[x][y];
x+=flag;
}
x+=flag*-1;
y+=flag*-1;
R--;
flag*=-1;
}
// A=1 , 아스키 > A=65
int integ = 0;
char alph = ' ';
String sr;
ArrayList<String> arr = new ArrayList<String>();
//ArrayList arr에 이진수를 5글자씩 잘라서 저장한다.
//5글자가 안 되면 저장하지 않는다.
for (int i = 0; i < (r * c / 5); i++) {
sr = "";
for (int j = 0; j < 5; j++) {
sr = sr + words[i * 5 + j];
}
arr.add(sr);
}
//앞뒤 공백문자를 제거한 후 이진수 문자열을 정수형으로 전환하고
//아스키코드에서 A=65임을 이용한다.
if (arr.size() != 0) {
while (arr.get(arr.size() - 1).equals("00000")) {
arr.remove(arr.size() - 1);
if(arr.size()==0)
break;
}
if (arr.size() != 0) {
while (arr.get(0).equals("00000")) {
arr.remove(0);
if(arr.size()==0)
break;
}
}
while (arr.size() > 0) {
integ = Integer.parseInt(arr.remove(0), 2);
if (integ != 0) {
alph = (char) (integ + 64);
System.out.print(alph);
} else
System.out.print(" ");
}
}
System.out.println();
N--;
}
}
}
다른 쉽게 풀 방법이 안 떠올라 과정을 그대로 나타내었다.
다만 출력 형식에는 나와있지 않은데 앞에 표시되는 공백도 제거해야한다.
달팽이 배열이 처음이라 너무 헷갈렸다