프로그래머스 문제를 풀어보면서 코딩 실력을 기르려고 한다. 우선 낮은 단계의 문제부터 풀어보면서 감을 잡고, 나중에 프로젝트를 만드는 것이 최종 목표이다.
소문자 26개를 가지고, 두가지의 문자열과 숫자 index를 입력받는다. 첫번째는 암호화된 문장, 두번째는 암호화 과정에서 규칙으로 존재하는 문자열, 숫자는 a = 1일 때 숫자 5라면 e = 6이 되는 방식이다.
#include <string>
#include <vector>
using namespace std;
string solution(string s, string skip, int index)
{
string answer = "";
int s_len = s.length(); // s의 원소 개수
int skip_len = skip.length(); // skip의 원소 개수
for (int i = 0; i < s_len; i++) // s의 i번째 원소
{
for (int j = 0; j < index; j++) // index번만큼 아스키코드에 더함
{
s[i] = s[i] + 1; // 아스키코드에 1더하기
for (int k = 0; k < skip_len; k++) // skip
{
if (s[i] == skip[k]) //skip에 있는 원소와 비교하기
{
s[i] = s[i] + 1;
k = - 1; // 중요!! *주의*
}
if (s[i] == 123) // 만약 z를 넘어 z 다음 원소의 아스키코드(z = 122)가 되었다면, 26을 빼 줘서 a로 바꿈
{
s[i] = s[i] - 26;
}
}
}
}
answer = s;
return answer;
}
가장 오랜 고민을 했던 부분은 바로 K에 -1를 대입하는 구문에서였다. 자꾸 오류와 정답인 testbench case가 번갈아가면서 나왔기 때문에, 코드의 메인스트림은 맞으나, 사소한 부분에서 오류가 발생할 것이라고 생각했기 때문에 하나하나 분석할 때 오랜 시간이 걸렸다.
그 문제는 바로 testbench skip 문자열이 내 생각엔 자동으로 sort되어 작용할 것이라고 생각했기에 발생한 문제였다. 만약 sort된 skip 문자열이라면, skip 원소와 비교하는 구문에서 그저 하나씩 차례로 검사하고 만약 skip과 s의 호출된 원소가 같다면, 그저 다음 아스키코드에 1을 더하여 다음 문자로 바꾸면 되는 것이었다.
그러나 주어진 문자열은 섞여있어서 만약 첫번째 케이스를 통과하더라도 다음 케이스 때 이전 아스키코드보다 작은 아스키코드를 가진 문자가 등장해버린다면 이전에 통과했던 s 문자가 이미 통과했던 첫번째 케이스에 적발될 가능성이 있기 때문이다.
따라서, 검사를 통하여 그것을 진행시키는 도중에 만약 skip 문자열에 적발되어서 아스키코드가 1 커질 경우, 다시 skip 문자열의 처음으로 돌아가 다시금 검사함으로써 이것을 시행하였다.
다만, for문에서 시행 시 k값이 실행 for문이 모두 실행 후 1 후행 증가하기 때문에 k = 0 으로 둘 경우에 K가 1에서 시작하여 0번 인덱스가 실행하지 않는다. 따라서 k를 -1로 두어야 재검사 시 k가 0에서 시작한다.
class에서 내부 멤버 함수를 사용하여 조금 더 편리하게 연산을 수행할 수 있음을 알게 되었다. 멤버 함수를 사용하지 않아도 문자열의 길이를 알아낼 수는 있지만 단 한줄로 끝내는 점은 정말 편했다.
그러나, 이런 이미 구현되어 있는 라이브러리를 이용할 때는 항상 그것이 무엇을 의미하고 어떤 방식으로 작동하는지 알고 사용하여야 함을 명심하게 되었다.