본문 바로가기
코딩테스트 준비/프로그래머스

[프로그래머스][C++] 둘만의 암호

by 스테디코디스트 2023. 10. 19.
반응형

<문제 소개>


<소스 코드>

#include <string>
#include <vector>
#include <map>

using namespace std;

string solution(string s, string skip, int index) 
{
    string answer = "";
    
    // 해당 단어를 만났을 때 스킵할지 여부
    map<char,bool> IsSkip;    
    
    for(int i = 0; i < skip.size(); i++)
    {        
        IsSkip[skip[i]] = true;
    }
        
    for(int i = 0; i < s.size(); i++)
    {
        char curWord = s[i]; // 현재 단어
                
        for(int j = 1; j <= index; j++)
        {        
            curWord++;
            
            // z를 넘어가는 경우
            if(curWord > 'z')
            {                
                curWord = 'a';                
            }        
            
            while(IsSkip[curWord])
            {
                curWord++;
                
                // z를 넘어가는 경우
                if(curWord > 'z')
                {                
                    curWord = 'a';                
                }  
            }
        }
        
        answer += curWord;
    }
    
    return answer;
}

<소스코드 2>

#include <string>
#include <vector>

using namespace std;

string solution(string s, string skip, int index) 
{
    string answer = "";

    for(auto v : s)
    {
        int t = 0;
        int c = v - 'a'; // 알파벳을 1~26 사이의 숫자로 변환
        
        while(t < index)
        {
            c++;
            
            // c를 26으로 나눈 나머지를 구해 해당 단어가 몇 번째 알파벳인지 구하고 'a'에 더해서 실제 단어를 구함           
            v = (c % 26) + 'a'; 
            
            // npos : -1 값을 가지는 상수로 find() 함수 수행 시에 찾는 문자열이 없을 때 반환한다.
            // 그러므로 skip하지 않는 경우에만 t를 증가시켜 한 번 바꿨음을 나타낸다.
            if(skip.find(v) == string::npos)
            {
                t++;
            }
        }
        
        answer += v;
    }
    
    return answer;
}

<풀이과정 1>

1. map을 이용해 해당 단어를 만났을 때 스킵할지의 여부를 결정하는 컨테이너를 생성한다.

2. skip을 반복하며 skip을 이루고 있는 단어들을 map IsSkip의 값을 true로 바꿔준다.

3. 주어진 문자열 s를 돌면서 각 단어들에 접근한다.

4. 각 단어별로 index만큼 뒤의 알파벳으로 바꿔줘야 하므로 index번 반복을 진행하며 알파벳을 바꾸는 작업을 진행한다.

5. 먼저 해당 단어를 다음 단어로 넘겨주고, 그 단어가 z를 넘어가는지 확인한다.

6. 이후 IsSkip을 확인하여 skip해야 되는 단어인지 판단하고, skip을 하지 않아도 되면 다음 반복으로 넘어간다.

7. 만약 skip을 해야된다면 해당 단어를 한 번 더 다음 단어로 넘겨주고, 해당 단어가 z가 넘어가는지 확인하는 작업을 단어가 skip하지 않아도 될때까지 반복해준다.

8. 각 단어마다의 반복(내부 for문)이 모두 끝나면 단어변환작업이 끝난 것이므로 answer에 해당 단어를 추가해준다.

9. 위의 과정을 s의 모든 단어에 대해 반복이 끝나고 answer를 리턴해준다.

 

<풀이과정 2>

1. s의 각 원소들을 v라는 변수에 담아 반복하며 진행

2. 반복자 t는 0으로 선언

3. 해당 단어를 1~26 사이의 숫자로 변환시킨 수 c를 선언

4. c를 증가시켜 다음 단어로 넘어갔음을 나타내고, 26으로 나눈 나머지를 이용해 알파벳의 몇 번째 단어인지 확인

5. 'a'에 나머지 값을 더해 v를 바꿔줌

6. find()함수를 이용해 skip에 v가 들어가는지 확인 후 들어가지 않는다면 반복자를 증가시키고, 들어가지 않는다면 다음 반복 진행

7. 위의 4-6의 과정을 t가 index보다 커질 때까지 반복하고, 반복이 끝나면 index만큼 뒤로 밀려난 단어 v를 answer에 넣어줌

8. 모든 반복이 끝나고 answer을 리턴해줌


<코멘트>

반복을 줄이기위해 map을 사용하였다.

z에서 a로 넘어가는 과정에서 예외가 많이 발생하였다.

z를 넘어가는 경우가 두 번 반복되는게 이쁘지가 않아서 어떻게 하면 이쁘게 풀 수 있을지 생각해보다가 잘 모르겠어서 다른 사람의 풀이를 보고 해당 코드를 추가했다.

 


<제출결과>