[문제]
https://softeer.ai/practice/info.do?idx=1&eid=804&sw_prbl_sbms_sn=171521
[풀이]
1. 5x5 암호표를 채운다.
25가지의 문자에 대해서 idx를 증가시켜가며 암호표를 채워준다. 행은 idx/5, 열은 idx%5로 나타낼 수 있고, 문자는 한번 씩 등장해야하므로 boolean 배열을 이용해 나왔는지 여부를 체크해준다.
2. 키를 두 자씩 쪼개서 저장한다. 같은 문자가 연속될 경우 X가 아니면 X를, X면 Q를 이어 붙여줘야 한다. 한문자씩 빼와 그 다음 문자와 비교하기 위해 Queue를 사용한다. 마지막 문자의 경우 예외적으로 XX도 허용함에 주의한다!
3. 암호화한다. 행, 열만 조건에 맞춰 바꿔주면 된다.
[코드]
package 시뮬레이션;
import java.util.*;
import java.io.*;
public class sof_804_플레이페어암호 {
static char[][] board;
static boolean[] check;
public static class Point{
int r, c;
Point(int r, int c){
this.r = r;
this.c = c;
}
}
public static void main(String[] args) throws Exception{
board = new char[5][5];
String message, key;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
message = br.readLine();
key = br.readLine();
check = new boolean[26];
String alphabets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//5x5 표를 채운다.
//PLAYFAIRCIPHERKEY
check['J'-'A'] = true;
int idx = 0;
for(int i=0; i<key.length(); i++){
char c = key.charAt(i);
if(check[c-'A']) continue;
board[idx/5][idx%5] = c;
check[c-'A'] = true;
idx++;
}
//사용되지 않은 알파벳 차례대로 채우기
for(int i=0; i<26; i++){
if(check[i]) continue;
board[idx/5][idx%5] = (char)(i+'A');
idx++;
}
//암호화하려는 메시지를 2자씩 나눈다
//HE L LO WO RL D
//HE LX LO WO RL DX
List<String> tokens = new ArrayList<>();
Queue<Character> q = new LinkedList<>();
for(int i=0; i<message.length(); i++){
q.offer(message.charAt(i));
}
while(!q.isEmpty()){
char c1 = q.poll();
if(q.isEmpty()){
tokens.add(String.valueOf(c1)+"X");
break;
}
if(c1==q.peek()){
char c2 = 'X';
if(c1=='X'){
c2 = 'Q';
}
tokens.add(String.valueOf(c1)+String.valueOf(c2));
}
else{
char c2 = q.poll();
tokens.add(String.valueOf(c1)+String.valueOf(c2));
}
}
//암호화하기
String encrypted = "";
for(String t:tokens){
char c1 = t.charAt(0);
char c2 = t.charAt(1);
Point p1 = find(c1);
Point p2 = find(c2);
//1. 같은 행에 존재한다면 오른쪽으로 한칸 이동한 문자로
if(p1.r==p2.r){
c1 = board[p1.r][(p1.c+1)%5];
c2 = board[p2.r][(p2.c+1)%5];
encrypted += String.valueOf(c1)+String.valueOf(c2);
}else if(p1.c==p2.c){
//2. 같은 열에 존재한다면 아래쪽으로 한칸 이동한 문자로
c1 = board[(p1.r+1)%5][p1.c];
c2 = board[(p2.r+1)%5][p2.c];
encrypted += String.valueOf(c1)+String.valueOf(c2);
}
else{
//3. 두 문자의 열 위치가 교환된 문자로
c1 = board[p1.r][p2.c];
c2 = board[p2.r][p1.c];
encrypted += String.valueOf(c1)+String.valueOf(c2);
}
}
System.out.println(encrypted);
}
public static Point find(char c){
for(int i=0; i<5; i++){
for(int j=0; j<5; j++){
if(board[i][j]==c){
return new Point(i, j);
}
}
}
return new Point(0, 0);
}
}
'알고리즘 공부 및 문제 풀이 > 소프티어(SOF)' 카테고리의 다른 글
[sof] 소프티어 <인증평가 5차 기출> 업무 처리 - 이진 트리 (0) | 2023.04.03 |
---|---|
[sof] 소프티어 <인증평가 5차 기출> 성적 평가 (Java) - 시뮬레이션 (0) | 2023.03.31 |
[sof] 소프티어 <21년 재직자 대회 본선> 거리 합 구하기 (Java) - DFS, 트리 (0) | 2023.03.31 |
[sof] 소프티어 <인증평가 4차 기출> 통근버스 출발 순서 검증하기 (Java) - 구간합 (0) | 2023.03.31 |
[sof] 소프티어 <인증평가 4차 기출> 슈퍼컴퓨터 클러스터 (Java) - 이분탐색 (0) | 2023.03.31 |