[SOFTEER] 3회 정기 코딩 인증평가 기출 - 플레이페어 암호

2 minute read

문제출처

문제접근

  • key 를 이용해서 5x5 보드를 완성한다. 알파벳 대문자의 등장 여부를 알 수 있도록 배열을 선언하고, 등장 여부를 확인하며 board를 채운다.
  • message 를 두문자씩 쪼갠 문자열을 벡터 컨테이너를 통해 담는다. 이때, 재귀호출을 통한 구현이 예외상황에 대해 대처하기 좋다.
    • 두문자가 같은 경우 앞문자 뒤에 ‘X’ 를 추가한다. 만약 앞문자가 ‘X’라면 ‘Q’를 추가하는데, 마지막 남은 한개의 문자가 ‘X’라면 ‘X’를 추가할 수 있다.
  • 같은 행에 있는지 확인하고, 문자를 바꿔준다.
  • 위 조건이 만족하지 않는다면 같은 열에 있는지 확인하고, 문자를 바꿔준다.
  • 두 조건이 모두 만족하지 않는다면 각자의 행에서 서로의 열에 위치한 문자로 바꿔준다.

구현

#include <iostream>
#include <string>
#include <vector>

using namespace std;
vector<vector<char>> board(5, vector<char>(5));

void InitBoard(string key){
	vector<int> alphabet(26,0); // J는 제외
	int r=0, c=0;
	for(int i=0; i<key.size(); i++){
		char ch = key[i];
		if(alphabet[ch-'A']==1) continue;
		alphabet[ch-'A']++;
		board[r][c++] = ch;
		if(c==5){
			r++; c=0;
		}
	}
	
	// 나머지 칸 채우기
	for(int i=0; i<26; i++){
		if(i=='J'-'A') continue;
		if(alphabet[i]==0) board[r][c++] = i+'A';
		if(c==5){
			r++; c=0;
		}
	}
}

void Recur(vector<string>& ret, string msg){
	if(msg.size()==0) return;
	if(msg.size()==1){
		msg += "X";
		ret.push_back(msg);
		return;
	}

	string str;
	if(msg[0]==msg[1]){
		str.push_back(msg[0]);
		if(msg[0]=='X') str.push_back('Q');
		else str.push_back('X');
		ret.push_back(str);
		Recur(ret, msg.substr(1));
	}
	else{
		str.push_back(msg[0]);
		str.push_back(msg[1]);
		ret.push_back(str);
		Recur(ret, msg.substr(2));
	}
}

vector<string> DivMessage(string msg){
	vector<string> ret;
	string str;

	if(msg.size()==1){
		str.push_back(msg[0]);
		str.push_back('X');
		ret.push_back(str);
		return ret;
	}
	Recur(ret, msg);
	return ret;
}

int CheckSameRow(string str){
	int x1, x2;
	for(int r=0; r<5; r++){
		for(int c=0; c<5; c++){
			if(str[0]==board[r][c]) x1=r;
			if(str[1]==board[r][c]) x2=r;
		}
	}
	if(x1==x2) return x1;
	else return -1;
}

int CheckSameCol(string str){
	int y1, y2;
	for(int r=0; r<5; r++){
		for(int c=0; c<5; c++){
			if(str[0]==board[r][c]) y1=c;
			if(str[1]==board[r][c]) y2=c;
		}
	}
	if(y1==y2) return y1;
	else return -1;
}

int main(int argc, char** argv)
{
	string msg, key;
	cin >> msg >> key;

	// board init
	InitBoard(key);
	vector<string> data = DivMessage(msg);

	string ans;
	for(int i=0; i<data.size(); i++){
		int r,c;
		char front, back;
		r = CheckSameRow(data[i]);
		c = CheckSameCol(data[i]);
		if(r!=-1){
			for(int c=0; c<5; c++){
				if(data[i][0]==board[r][c]){
					if(c==4) front = board[r][0];
					else front = board[r][c+1];
				}
				if(data[i][1]==board[r][c]){
					if(c==4) back = board[r][0];
					else back = board[r][c+1];
				}
			}
			data[i][0] = front; data[i][1] = back;
		}
		else if(c!=-1){
			for(int r=0; r<5; r++){
				if(data[i][0]==board[r][c]){
					if(r==4) front = board[0][c];
					else front = board[r+1][c];
				}
				if(data[i][1]==board[r][c]){
					if(r==4) back = board[0][c];
					else back = board[r+1][c];
				}
			}
			data[i][0] = front; data[i][1] = back;
		}
		else{
			int r1,r2,c1,c2;
			for(int r=0; r<5; r++){
				for(int c=0; c<5; c++){
					if(data[i][0]==board[r][c]){
						r1=r, c1=c;
					}
					if(data[i][1]==board[r][c]){
						r2=r, c2=c;
					}
				}
			}
			data[i][0] = board[r1][c2];
			data[i][1] = board[r2][c1];
		}
		ans += data[i];
	}

	cout << ans << endl;

	return 0;
}

Categories:

Updated:

Leave a comment