Post

[swea-D2] 27801. 변형된 카이사르 암호 해독

SWEA 소피 제르멩 소수 문제를 JAVA를 이용해 구현으로 해결하는 방법을 설명합니다.

[swea-D2] 27801. 변형된 카이사르 암호 해독

🙋‍♂️ 문제 설명

카이사르 암호(Caesar cipher)는 시저 암호라고도 불리며,
알파벳의 각 문자를 일정한 거리만큼 이동시켜 다른 문자로 바꾸는 암호 방식이다.

알파벳의 끝을 넘어가는 경우에는 다시 처음으로 돌아간다.

예를 들어 Z를 오른쪽으로 3칸 이동시키면 C가 된다.


암호 해독 규칙

일반적인 카이사르 암호에서는 모든 문자를 같은 거리만큼 이동하지만,
이 문제에서는 문자의 위치에 따라 이동하는 방향과 이동량이 달라진다.

암호문의 첫 번째 문자부터 차례대로 다음 규칙을 적용한다.

  1. 홀수 번째 문자는 알파벳 순서의 오른쪽으로 해당 위치만큼 이동한다.
  2. 짝수 번째 문자는 알파벳 순서의 왼쪽으로 해당 위치만큼 이동한다.
  3. Z에서 오른쪽으로 이동하면 다시 A부터 이어진다.
  4. A에서 왼쪽으로 이동하면 다시 Z부터 이어진다.

즉, 각 위치에서의 이동 방향과 이동량은 다음과 같다.

위치이동
1번째+1
2번째-2
3번째+3
4번째-4
5번째+5
6번째-6

여기서 +는 알파벳 순서의 오른쪽으로 이동하는 것을,
-는 알파벳 순서의 왼쪽으로 이동하는 것을 의미한다.


예시

암호문 XQRGVTPQE가 주어졌다고 하자.

각 문자에 규칙을 적용하면 다음과 같다.

구분1번째2번째3번째4번째5번째6번째7번째8번째9번째
암호문XQRGVTPQE
이동+1-2+3-4+5-6+7-8+9
해독 결과YOUCANWIN

따라서 암호문을 해독한 결과는

1
YOUCANWIN

이 된다.

만약 N = 3이라면, 해독된 문자열을 앞에서부터 3글자씩 나누어 각 단어 사이에 하나의 공백을 추가한다.

1
YOU / CAN / WIN

따라서 완성된 문장은 다음과 같다.

1
YOU CAN WIN

문제

각 테스트 케이스에는 정수 N과 알파벳 대문자로 이루어진 암호문 S가 주어진다.

주어진 규칙에 따라 암호문 S를 해독하고,
해독된 문자열을 앞에서부터 N글자씩 나누어 하나의 문장으로 만들어 출력하라.

나누어진 각 문자열 사이에는 하나의 공백을 추가한다.


입력

첫 번째 줄에 테스트 케이스의 수 T가 주어진다.

각 테스트 케이스는 두 줄로 구성된다.

  • 첫 번째 줄에는 해독된 문자열을 몇 글자씩 나눌 것인지를 나타내는 정수 N이 주어진다.
  • 두 번째 줄에는 알파벳 대문자로만 이루어진 암호문 S가 주어진다.

제약 사항

  1. 암호문 S는 알파벳 대문자 A부터 Z까지만으로 이루어진다.
  2. 문자열의 첫 번째 문자의 위치는 1이다.
  3. 알파벳의 범위를 벗어나 이동하는 경우 AZ가 서로 이어져 있다고 생각한다.
  4. 1 ≤ N ≤ |S|
  5. 해독된 문자열의 길이는 N의 배수이다.

출력

각 테스트 케이스마다 암호문을 주어진 규칙에 따라 해독한다.

해독된 문자열을 N글자씩 나누고, 나누어진 문자열 사이에 하나의 공백을 추가하여 완성된 문장을 출력한다.

각 테스트 케이스의 결과는 다음 형식으로 출력한다.

1
#tc 정답

tc는 테스트 케이스의 번호이며 1부터 시작한다.


입력 예시

1
2
3
4
5
6
7
8
9
4
3
XQRQVEGWKGXZOIEOXMJUSPUW
4
XQRVOOFMNSAXPCXUBLHSHWOK
5
UCIYZZKCKRPNBJPFAAKY
6
KKQXGKMPZXVEPFPQCWJBFJJC

출력 예시

1
2
3
4
#1 YOU MAY NOT WIN BUT YOU CAN TRY
#2 YOUR TIME WILL COME STAY CALM
#3 VALUE TRUTH ABOVE PRIDE
#4 LITTLE THINGS CREATE CHANGE



✅ 정답 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;


public class Solution {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		for (int tc = 1; tc < T+1; tc++) {
			int space_cnt = Integer.parseInt(br.readLine());
			String S = br.readLine();
			
			// space_cnt 만큼 채우면 공백 추가하고 다시 cnt = 0으로 갱신, i < N-1 미만일때만 유효
			int cnt = 0;
			StringBuilder sb = new StringBuilder();
			
			// 암호문S의 길이는 26
			for (int i = 0; i < S.length(); i++) {
				char cur_ch = S.charAt(i);
				int step = i+1;
				
				// 기본적으로 step은 양수처리니 홀수 idx일때만 처리하면 된다.
				if (i % 2 == 1) step -= 2*step;
				
				// 새로운 idx
				int idx = (cur_ch - 'A' + 26 + step) % 26;
				
				// 새로운 글자
				char new_ch = (char) (idx + 'A');
				sb.append(new_ch);
				cnt++;
				
				// space_cnt 개씩 나누고, idx가 맨마지막 미만일때만
				if (cnt == space_cnt && i <= S.length()-2) {
					sb.append(" ");
					cnt = 0;
				}
			}
			// 출력
			System.out.println("#" + tc + " " + sb.toString());
			
		}
	}
}
This post is licensed under CC BY 4.0 by the author.

Trending Tags

반갑습니다 무엇을 도와드릴까요?