[백준] 2714번: 문자를 받은 승환이_java

응갱·2022년 10월 11일
0

백준

목록 보기
27/56
post-thumbnail

https://www.acmicpc.net/problem/2714

📎문제

규현이는 승환이에게 사랑을 담은 문자 메시지를 자주 보낸다. 이것을 남에게 보이기 싫었던 규현이는 승환이와 비밀 규칙을 만들었다.

규현이는 비밀 메시지를 만들기 위한 행렬의 행의 수 R과 열의 수 C를 정했다. 그 다음 다음과 같은 규칙으로 비밀 메시지를 만든다.

  1. 모든 글자는 알파벳 대문자와 공백으로 이루어져 있다.
  2. 글자는 다음과 같이 숫자로 바뀐다. 공백 = 0, A = 1, B = 2, ..., Y = 25, Z = 26

먼저 규현이는 문자를 위 규칙을 이용해 글자를 숫자로 바꾼 다음에 이것은 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--;

		}

	}

}

📎코드 해석

다른 쉽게 풀 방법이 안 떠올라 과정을 그대로 나타내었다.
다만 출력 형식에는 나와있지 않은데 앞에 표시되는 공백도 제거해야한다.

🥔후기

달팽이 배열이 처음이라 너무 헷갈렸다

profile
🥔 한 덩이

0개의 댓글