https://school.programmers.co.kr/learn/courses/30/lessons/17682
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
1. 문제 설명
카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.
- 다트 게임은 총 3번의 기회로 구성된다.
- 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
- 점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (점수1 , 점수2 , 점수3 )으로 계산된다.
- 옵션으로 스타상(*) , 아차상(#)이 존재하며 스타상(*) 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다. 아차상(#) 당첨 시 해당 점수는 마이너스된다.
- 스타상(*)은 첫 번째 기회에서도 나올 수 있다. 이 경우 첫 번째 스타상(*)의 점수만 2배가 된다. (예제 4번 참고)
- 스타상(*)의 효과는 다른 스타상(*)의 효과와 중첩될 수 있다. 이 경우 중첩된 스타상(*) 점수는 4배가 된다. (예제 4번 참고)
- 스타상(*)의 효과는 아차상(#)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(#)의 점수는 -2배가 된다. (예제 5번 참고)
- Single(S), Double(D), Triple(T)은 점수마다 하나씩 존재한다.
- 스타상(*), 아차상(#)은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.
0~10의 정수와 문자 S, D, T, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.
입력 형식
"점수|보너스|[옵션]"으로 이루어진 문자열 3세트.
예) 1S2D*3T
- 점수는 0에서 10 사이의 정수이다.
- 보너스는 S, D, T 중 하나이다.
- 옵선은 *이나 # 중 하나이며, 없을 수도 있다.
출력 형식
3번의 기회에서 얻은 점수 합계에 해당하는 정수값을 출력한다.
예) 37
입출력 예제
예제dartResultanswer설명
예제 | dartResult | answer | 설명 |
1 | 1S2D*3T | 37 | 1¹ * 2 + 2² * 2 + 3³ |
2 | 1D2S#10S | 9 | 1² + 2¹ * (-1) + 10¹ |
3 | 1D2S0T | 3 | 1² + 2¹ + 0³ |
4 | 1S*2T*3S | 23 | 1¹ * 2 * 2 + 2³ * 2 + 3¹ |
5 | 1D#2S*3S | 5 | 1² * (-1) * 2 + 2¹ * 2 + 3¹ |
6 | 1T2D3D# | -4 | 1³ + 2² + 3² * (-1) |
7 | 1D2S3T* | 59 | 1² + 2¹ * 2 + 3³ * 2 |
2. 문제 풀이
- 0 ~ 10 에 보너스로 계산된 점수를 벡터에 담는다.
- 옵션이 있다면 *(스타상)인지 #(아차상)인지 판단후에 스타상이라면 *2 아차상이라면 * -1을 해준다.
반복문안에서 0 ~ 10사이의 숫자라면 tmp작업공간에 잠깐 저장했다가 해당 숫자의 보너스 점수가 'S' 'D' 'T'중 어떤것인지 판별후 준비된 벡터에 값을 저장한다. 만약 *(스타상)이나 #(아차상)이 존재한다면 벡터에 담겨진 값들을 조건에 맞게 계산해준다.
3. 소스코드(잘못된 풀이)
처음에는 위에 적은것처럼 설계하고 문제를 풀었는데 테스트케이스 4번만 틀리는 결과가 반복됐다. 논리적오류가 없는지 한참을 고민했고 스타상을 계산하는 부분에서 점수를 담은 score의 크기가 1일때는 for문이 동작하지 않는다는 사실을 알아냈다. for문의 반복조건에서 score.size()는 size_t(양의 정수)를 반환하는데 크기가 1일때 -2를 하니 음수가 되어 제대로 작동하지 않는것이었다.
#include <string>
#include <vector>
#include <cmath>
using namespace std;
int solution(string dartResult) {
int answer = 0;
vector<int> score;
string tmp = "";
for(int i=0; i<dartResult.size(); ++i)
{
if('0' <= dartResult[i] && dartResult[i] <= '9')
tmp += dartResult[i];
if(dartResult[i] == 'S')
{
score.push_back(stoi(tmp));
tmp = "";
}
else if(dartResult[i] == 'D')
{
score.push_back(pow(stoi(tmp),2));
tmp = "";
}
else if(dartResult[i] == 'T')
{
score.push_back(pow(stoi(tmp),3));
tmp = "";
}
if(dartResult[i] == '*')
{
for(int j= score.size() - 1; j >= score.size() - 2; --j)
{
if(j < 0)
break;
score[j] *= 2;
}
}
else if(dartResult[i] == '#')
score[score.size() -1] *= -1;
}
for(auto& s : score)
answer += s;
return answer;
}
3 - 2. size()함수
아래는 Visual Studio에서 size()함수가 반환하는 값보다 큰 값을 뺄셈해 음수가 되도록 해봤다.의도했던 -1의 값이 아닌 이상한 값이 출력되었다. 아마 size_t형이 음수가 될 수 없으니 양수로 표현할 수 있는 가장 큰 값이 반환되지 않았나 싶다.
4. 소스코드(수정)
문제를 알았으니 생각나는 방법은 두가지였다. for문에서 cast연산자를 사용하거나 int형변수를 선언해 size()함수의 반환값을 담아 문제를 해결하는것이었다. 두가지 방법모두 잘 되는것을 볼 수 있다.
if(dartResult[i] == '*')
{
int idx = score.size();
for(int j= idx - 1; j >= idx - 2; --j)
{
if(j < 0)
break;
score[j] *= 2;
}
}
if(dartResult[i] == '*')
{
for (int j = score.size() - 1; j >= (int)(score.size() - 2); --j)
{
if (j < 0)
break;
score[j] *= 2;
}
}
'코딩테스트 > 프로그래머스' 카테고리의 다른 글
[프로그래머스] C++ LV1 콜라츠 추측 (0) | 2025.04.14 |
---|---|
[프로그래머스]C++ LV1 소수 찾기 (1) | 2025.04.11 |
[프로그래머스]C++ LV1 3진법 뒤집기 (1) | 2025.02.11 |
[프로그래머스]C++ LV1 최대공약수와 최소공배수 (1) | 2025.02.03 |
[프로그래머스] C++ LV1 같은 숫자는 싫어 (1) | 2025.01.09 |