문제 설명
네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영다어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다.
다음은 숫자의 일부 자릿수를 영단어로 바꾸는 예시입니다.
- 1478 →"one4seveneight"
- 234567 →"23four5six7"
- 10203 →"1zerotwozero3"
이렇게 숫자의 일부 자릿수가 영단어로 바뀌어졌거나, 혹은 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어집니다. s가 의미하는 원래 숫자를 return 하도록 solution 함수를 완성해주세요.
참고로 각 숫자에 대응되는 영단어는 다음 표와 같습니다.
숫자 | 영단어 |
0 | zero |
1 | one |
2 | two |
3 | three |
4 | four |
5 | five |
6 | six |
7 | seven |
8 | eight |
9 | nine |
제한사항
- 1<=s의 길이<=50
- s가 "zero"또는 "0"으로 시작하는 경우는 주어지지 않습니다.
- return 값이 1이상 2,000,000,000 이하의 정수가 되는 올바른 입력 s로 주어집니다.
입출력 예
s | result | 설명 | ||
"one4seveneight" | 1478 | 문제 예시와 같습니다. | ||
"23four5six7" | 234567 | 문제 예시와 같습니다. | ||
"2three45sixseven" | 234567 | "three"는 3, "six"는 6, "seven"은 7에 대응되기 때문에 정답은 입출력 예 #2와 같은 234567이 됩니다. 입출력 예 #2와 #3과 같이 같은 정답을 가리키는 문자열이 여러가지 나올 수 있습니다. |
||
"123" | 123 | s에서 영단어로 바뀐 부분이 없습니다. |
문제 풀이
풀이 언어 : C++
#include <string>
#include <vector>
#include <cctype>
#include <algorithm>
using namespace std;
int solution(string s) {
int answer = 0;
string string_num=""; // 문자를 만났을 때 영어 숫자가 온전히 완성될 때까지 문자를 저장하는 변수
string answer_s = ""; // int형으로 형변환 하기 전 string형 정답을 저장하는 변수
vector<string> numberEng = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; // 영어 숫자 배열
for(int i=0; i<s.length(); i++)
{
if(isdigit(s[i])==0) // 문자일 경우
{
string_num+=s[i]; // string_num에 문자 저장
if(find(numberEng.begin(), numberEng.end(), string_num)!=numberEng.end()) // string_num에 영어 숫자가 완성되었을 때
{
// string_num을 숫자로 변환
answer_s+=to_string(find(numberEng.begin(), numberEng.end(), string_num)-numberEng.begin()); // answer_s에 숫자(string) 저장
string_num=""; // string_num 비우기(초기화)
}
}
else // 숫자일 경우
{
answer_s+=s[i]; // answer_s에 숫자(string) 저장
}
}
answer=stoi(answer_s); // answer_s 변수 int형으로 형변환
return answer;
}
매개변수로 들어온 s를 모두 훑어보면서 숫자인지 문자인지 구별하여 각각 동작을 다르게 구현하면 될 것 같다. 문자가 들어온다면 우선 문자를 저장하고 저장된 문자열이 모여서 숫자 영단어가 되면 영단어를 진짜 숫자로 변환한다. 변환된 숫자는 정답에 저장한다. 만약 숫자가 들어올 경우 그대로 정답에 저장한다. 마지막으로 문자열로 저장되어 있던 정답을 int형으로 형변환해주면 될 것이다.
s를 모두 훑어보기 위해서 반복문을 사용하였다. 반복의 횟수는 s의 길이 s.length()만큼 하였다. 그리고 s[i]가 문자인지 숫자인지 확인하기 위해서 isdigit()함수를 사용하였다. 이전에도 한번 사용한적 있는데 여기서 또 쓰게될 줄 몰랐다. isdigit(s[i])가 0이 나오면 문자, 0이 아닌 다른 수가 나오면 숫자가 들어있다는 뜻이므로 경우를 나누기엔 충분하다.
string_num은 s를 돌다 나오는 문자들을 저장한다. 저장은 영단어 숫자가 완성될 때까지 하며 영단어 숫자가 완성되는 순간 초기화 한다. answer_s는 정답을 저장한다. 근데 int가 아닌 string형으로 저장한다. ing형으로 저장하려면 자릿수를 생각해야하고 10의 제곱들을 곱해서 더해야하는데 그러는 것보다 문자열로 하는 것이 낫다고 생각했다.
문자열일 경우 string_num에 문자를 저장한다. 그리고 string_num이 영단어 숫자가 되었는지 find() 함수를 이용해 확인한다. find() 함수를 이용하여 numberEng에 string_num이 있다면 영단어가 완성되었다는 뜻이므로 answer_s에 진짜 숫자로 변환된 값을 저장한다. 이 때 숫자 영단어를 진짜 숫자로 바꾸는 작업 또한 find()함수를 이용하였다. numberEng 벡터는 인덱스 값과 같은 영단어 숫자를 요소로 가진다. 예를 들어 0번째 요소는 "zero", 5번째 요소는 "five" 이다. 따라서 find()함수에서 string_num과 같은 값의 위치를 찾아주는 find()에서 numberEng.begin()을 빼주면 인덱스를 구할 수 있게 된다. 그 후 string_num은 초기화시킨다.
만약 숫자인 경우 answer_s에 값을 저장한다. 모든 반복문이 끝나고 나서는 stoi() 함수를 이용하여 asnwer_s를 int로 형변환 해주고 값을 리턴한다.
참고 사항
find(iterator begin, iterator end, a) 함수를 이용해 a를 찾은 위치를 인덱스로 받을 수도 있다. find 함수의 반환값은 iterator이다. 따라서 index를 반환하는 것은 아닌데 index를 반환하게 하기 위해서 find()-v.begin()을 하면 된다. find함수의 결과값에 벡터의 처음 위치를 빼면 인덱스가 나오게 된다.
answer_s+=to_string(find(numberEng.begin(), numberEng.end(), string_num)-numberEng.begin()); // answer_s에 숫자(string) 저장
오답 노트
영단어 숫자가 두개가 연달아 있는 경우를 파악하지 못해서 오류가 발생했었다. 예를 들어 "1zeroone45"의 경우 zero와 one이 붙어 있는데 이 경우를 신경쓰지 않고 문자에서 숫자로 바뀌는 순간이 영단어가 완성되는 순간으로 정의하고 코딩하였었다.
문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/81301
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
'Code KATA > 알고리즘 코드카타' 카테고리의 다른 글
[2025.01.10] 3진법 뒤집기 (0) | 2025.01.10 |
---|---|
[2025.01.09] 최대공약수와 최소공배수 (0) | 2025.01.09 |
[2025.01.08] 추억 점수 (0) | 2025.01.08 |
[2025.01.08] 직사각형 별찍기 (0) | 2025.01.07 |
[2025.01.07] 행렬의 덧셈 (0) | 2025.01.07 |