궤도
[EPPER] 11회 8번 본문
문제
풀이
머리를 엄청 쓴 것 치곤 코드가 짧게 나오는 문제이다. 코드의 2/3 정도가 입력받은 문자를 가공하는 과정이고, 이마저도 switch가 아니라 문자열 배열을 사용했으면 훨씬 짧아졌을 것이다. 문제를 따라 해야할 일을 차근차근 해보자.
먼저 암호화할 메세지를 입력받고, 해당 메세지의 길이가 7의 배수인지 확인한다. 7의 배수가 아니라면 7의 배수가 될 때까지 알파벳을 순서대로 뒤에 붙여준다. 많이 붙여봤자 6개라 switch를 썼는데 이렇게 축소할 수 있다.
char concat_arr[7] = "abcdef";
for(int i = 0; i < concat_cnt; i++)
m_arr[length++] = concat_arr[i];
실제로 돌려보지 않아서 문법오류가 있을 수도 있는데 논리는 맞을 것이다. 이러면 21줄은 줄어든다.
메세지를 가공했으니 키값을 가공할 차례이다. 그냥 int로 받은 키를 자릿수별로 잘라서 key_arr에 저장한다. 키값이 뒤집혀서 저장되는 것을 막기 위해 뒤에서부터 저장한다. 키값은 무조건 7자리이니까 이렇게 저장해도 별 문제 없다.
모든 준비가 끝났으니 마지막으로 암호화한 메세지를 만든다. 한줄이지만 복잡해 보일 수 있다. 입력 예2를 이용해 설명해보겠다.
i=0 일 때 그니까 우린 새로운 암호문의 첫글자를 가져오려고 한다. 해당 위치의 키값이 뭔지 살펴보니 3이다. (key_arr[0%7]) 근데 다들 알겠지만 문자열의 인덱스는 0부터 시작한다. 그래서 1을 빼준다. 그럼 우린 기존 메세지의 [2] index 값을 가져오게 되고, 그건 f이다.
(i/7)*7 의 존재이유를 알아보기 위해 i를 8로 바꿔보자. 일단 key_arr[8%7] = 1 이다. informationabc를 7개씩 informa/tionabc로 나누면 우린 이번에 두번째 구역에서 문자를 가져와야 한다. 그래서 (i/7)*7이 필요한 것이다. 해당 값은 0, 7, 14...같이 7의 배수로 진행될 것이다. 구역을 건너뛰는 용도라고 생각하면 될 것 같다. 아무튼 이 과정을 통해 무사히 문자 t를 가져왔다. 생각을 많이 해야 했던 문제였다.
소스코드
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main() {
char m_arr[102]; //암호화할 배열
char n_arr[102]; //암호화한 배열
int key_arr[7]; //key값 저장할 배열
int key;
scanf("%s", &m_arr);
scanf("%d", &key);
int length = strlen(m_arr);
if (length % 7 != 0) { //7로 안나눠 떨어지면 뒤에 더 붙여야 함
int concat_cnt = 7 - (length % 7); //몇 개나 붙여야?
for (int i = 0; i < concat_cnt; i++) {
switch (i) { //그냥 6개니까 노가다로 스위치 돌림
case 0:
m_arr[length++] = 'a';
break;
case 1:
m_arr[length++] = 'b';
break;
case 2:
m_arr[length++] = 'c';
break;
case 3:
m_arr[length++] = 'd';
break;
case 4:
m_arr[length++] = 'e';
break;
case 5:
m_arr[length++] = 'f';
break;
}
}
}
for (int i = 6; i >= 0; i--) { //키 값 분리해서 저장하는데 순서 반대로 안되도록 뒤부터 넣음
key_arr[i] = key % 10;
key /= 10;
}
for (int i = 0; i < length; i++) { //i=3 이고, key=7654321 이면 n_arr[i] = m_arr[3]. 0부터 저장해서 그런 것.
n_arr[i] = m_arr[key_arr[i % 7] + (i / 7) * 7 - 1];
printf("%c", n_arr[i]);
}
}