81301. 숫자 문자열과 영단어

2022-05-01
프로그래머스 81301번 풀이

이 글은 Obsidian에서 마이그레이션되었으며, 그 과정에서 AI의 도움을 받았습니다. 오류나 누락된 내용이 있다면 댓글로 알려주세요!

문제

코딩테스트 연습 - 숫자 문자열과 영단어 | 프로그래머스 스쿨

풀이

아이디어

숫자가 있는 부분은 그대로 넣어주고, 문자가 있는 부분은 문자 부분대로 잘라서 숫자로 변환해서 넣어주면 된다.

문제는 문자 부분을 어디까지 잘라야 하는지인데… 숫자가 등장할 때 까지 포인터를 옮기자니 seveneight 같은 경우에는 자르기가 곤란하다.

그래서 문자가 시작하는 시점부터, 영단어에 대응되는 숫자를 저장해둔 map digit_list에 해당하는 key가 있을 때 까지 반복해서 포인터를 옮겨주는 방법을 사용하기로 했다.


이렇게 해서 문제를 풀긴 했는데 풀고 나서 다른 분들의 코드를 구경하다가 regex라는 것을 발견하고 좀 찾아봤더니 정규 표현식을 지원하는 라이브러리였다…

regex 라이브러리의 regex_replace 함수를 사용하면 원하는 패턴의 문자열을 치환할 수 있다.

#include <regex>
#include <string>
	...
	s = regex_replace(s, regex("zero"), "0");
	...
	answer = stoi(s);
	return (answer);

이러면 지정한 패턴에 맞게 s에 치환이 된다. 이 문제에서는 영단어들 중에서 어떤 단어에 포함되는 그런 영단어가 없어서 이런 식으로 풀어도 되나? 하고 생각했는데 또 생각해보니까 순서만 잘 조정해주면 포함되는 관계에 있는 패턴이라도 잘 치환이 될 것 같다.

우와… 정규식을 사용할 수 있다는 것이 엄청 유용할 것 같아서 좀 더 자세히 읽어봐야겠다. (참고: 씹어먹는 C++ - <17 - 2. C++ 정규 표현식() 라이브러리 소개>)

코드

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

using namespace std;

int solution(string s) {
    int answer = 0;

    map<string, int> digit_list = {{"zero", 0}, {"one", 1}, {"two", 2}, {"three", 3}, {"four", 4}, {"five", 5}, {"six", 6}, {"seven", 7}, {"eight", 8}, {"nine", 9}};
    int idx = 0, len = s.length();
    int start;
    string str;


    while (idx < len)
    {
        if (s[idx] >= '0' && s[idx] <= '9')
        {
            answer = answer * 10 + (s[idx] - '0');
            idx++;
            continue;
        }
        start = idx;
        idx++;
        while (idx < s.length() && (s[idx] >= 'a' && s[idx] <= 'z'))
        {
            idx++;
            str = s.substr(start, idx - start + 1);
            if (digit_list.find(str) != digit_list.end())
            {
                answer = answer * 10 + digit_list[str];
                break;
            }
        }
        idx++;
    }

    return answer;
}