카카오 문제를 풀어보자. 두려워 하지마라. 할 수 있다! 😁

안녕하세요! 두두코딩 입니다 ✋
오늘은 숫자 문자열과 영단어 문제를 풀어보겠습니다.

🖇 소스코드에 마우스를 올리고 copy 버튼을 누를 경우 더 쉽게 복사할 수 있습니다!

궁금한 점, 보안점 남겨주시면 성실히 답변하겠습니다. 😁
+ 감상평 댓글로 남겨주시면 힘이됩니다. 🙇

문제

해당 문제는 2021 카카오 채용 연계형 문제 중 숫자 문자열과 영단어 문제입니다.
문제를 보시려면 여기를 클릭해주세요! (저작권 문제로 링크로 공유드립니다.)

풀이

해당 문제는 문자열 함수 중 substr()compare() 함수를 활용하여 풀었다.

level 1번 문제라 생각의 전환만 잘 한다면 누구나 풀 수 있다고 생각한다. (카카오라 두려워 하지마시오!! 🤐)

접근과정

아래의 그림을 통해 접근과정을 확인해보자.

wordtonumber

해당 문제에서는 위의 그림과 같이, 23four5six7 와 같은 문자가 주어졌을 때, 영어로 된 부분을 숫자 로 변환 후 출력하는 문제이다.

해당 문제에서 핵심은 숫자로된 영단어를 구별 할 수 있느냐이다. 영단어를 어떻게 구별할지 생각해보면, 앞의 2자리만 참고해 어떤 숫자인지 판별해 변환해주면 문제가 해결 될 수 있다.

예를들어, two와 three를 찾아보자. 만약 1 자리만 비교하게 된다면 t로 구별할 수 없을 것이다. 하지만, 2 자리로 비교 할 경우 tw 는 2이고, th는 3이다 라고 구별할 수 있을 것이다.

본인은 해당 기법을 적용해 두 가지 방법으로 문제를 풀었다.

🌱 첫 번째 방법은 원시적 방법으로 if else문을 모든 케이스로 구별하고 푸는 방법이다.

🌱 두 번째 방법은 if else 문을 줄여 코드의 깔끔성을 위해 for loop로 해결한 방법이다.

두 번째 방법에 대해 조금 자세하게 설명해보자면, zero 부터 nine까지 10개의 문자열 배열을 만든다. 문자열 배열이 0부터 9까지 시작하기 때문에 index영어 문자열이 문제의 표와 같이 접근 가능하게 된다. 아래의 코드를 참고하자.

string numbers[10] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

그리고 인자로 전달받은 문자를 순회 하면서 현재 문자가 숫자인지 판별한다. 만약 숫자가 아니라면, 아래의 코드와 같이 for loop를 순회한다. 순회할 때, 초점은 j의 인덱스이다. j의 시작이 3이고, 끝이 5이다. 왜냐하면 numbers의 배열에 들어간 영어로된 숫자의 가장 짧은 길이가 3, 가장 긴 길이가 5 이기 때문이다.

따라서, 인자로 전달받은 문자를 substr(s, 3 or 4 or 5)로 잘라보며, 해당 문자와 numbers 배열 내 존재하는 문자들 중 같은 것이 있는지 확인해 만약 같은 것이 있다면 답에 추가 하고 인덱스 증가 시켜준다.

인덱스를 증가시켜주는 이유는 전달받은 문자를 하나씩 비교하기 때문이다.

구체적으로, zero라는 문자는 z를 비교할 때, substr(s, 4)zero라는 문자를 추출할 수 있다. 이후 numbers와 비교하고, zero라는 문자는 전달받은 문자열 s 에서 제거해줘야한다. 실제 제거하지 않고 인덱스를 증가 시키는 방법으로 제거하는 효과 를 내는 것이다.

해당 설명한 부분을 소스코드로 확인해보자.

 for (int i = 0; i < s.size(); i++) {

        // 숫자 인지 검사하는 부분
        char isNumber = s[i] - '0';
        if (isNumber >= 0 && isNumber < 10) {
            answer += s[i];
            continue;
        }

        // 해당 flag는 2중 for loop를 빠져나가기 위한 트릭이다.
        bool check_flag = false;

        // 문자열 사이즈 최소 3, 최대 5
        for (int j = 3; j <= 5; j++) {
            // 떼어본다.
            string changeStr = s.substr(i,j);

            // 동일한 문자열 있는지 돌면서 확인
            for (int k = 0; k < 10; k++) {
                if (! changeStr.compare(numbers[k])) {
                    i += (numbers[k].size() - 1);
                    answer += '0' + k;
                    check_flag = true;
                }
            }
            if (check_flag) break;
        }

소스코드

소스 코드는 두가지 버전으로 제공한다.

🌱 첫 번째 방법은 if else 사용

#include <vector>
#include <string>

using namespace std;

int solution(string s) {

    string answer;

    for (int i = 0; i < s.size(); i++) {
        char isNumber = s[i] - '0';
        if (isNumber >= 0 && isNumber < 10) {
            answer += s[i];
            continue;
        }

        string changeStr = s.substr(i, 2);
        if (!changeStr.compare("ze")) {
            i += 3;
            answer += '0';
        } else if (!changeStr.compare("on")) {
            i += 2;
            answer += '1';
        } else if (!changeStr.compare("tw")) {
            i += 2;
            answer += '2';
        } else if (!changeStr.compare("th")) {
            i += 4;
            answer += '3';
        } else if (!changeStr.compare("fo")) {
            i += 3;
            answer += '4';
        } else if (!changeStr.compare("fi")) {
            i += 3;
            answer += '5';
        } else if (!changeStr.compare("si")) {
            i += 2;
            answer += '6';
        } else if (!changeStr.compare("se")) {
            i += 4;
            answer += '7';
        } else if (!changeStr.compare("ei")) {
            i += 4;
            answer += '8';
        } else if (!changeStr.compare("ni")) {
            i += 3;
            answer += '9';
        }
    }

    return stoi(answer);
}

🌱 두 번째 방법은 for loop 사용

#include <vector>
#include <string>

using namespace std;

int solution(string s) {

    string numbers[10] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
    string answer;

    for (int i = 0; i < s.size(); i++) {
        char isNumber = s[i] - '0';
        if (isNumber >= 0 && isNumber < 10) {
            answer += s[i];
            continue;
        }
        bool check_flag = false;
        for (int j = 3; j <= 5; j++) {
            string changeStr = s.substr(i,j);

            for (int k = 0; k < 10; k++) {
                if (! changeStr.compare(numbers[k])) {
                    i += (numbers[k].size() - 1);
                    answer += '0' + k;
                    check_flag = true;
                }
            }
            if (check_flag) break;
        }
    }

    return stoi(answer);
}

Appendix

문제가 아주 어렵지는 않아, 주석 코드는 생략하고자 한다.

(모든 사람이 동일한 지식 수준을 갖고 있다고 생각하지 않는다. 본인도 모르는 부분이 많다. 혹시, 필요하다면 과감하게 댓글에 모르는 부분을 적어 물어보자! 😸)

해당 문제는 if else 사용 풀이for loop 사용 풀이 어느 것으로 풀어도 상관없다. 코드상 길이가 짧아 진다 정도지, 데이터 그렇게 많지않아 효율성을 따질 문제는 아닌 것 같다. 그냥 방향을 두 가지로 생각해 볼 수 있다 정도로만 이해하고, 핵심인 substr() 사용과 문자 2자리 비교 만 기억하자.