https://tech.kakao.com/2017/09/27/kakao-blind-recruitment-round-1/
저번 문제에 이어 오늘은 다트게임 문제를 풀어 보겠습니다.
2. 다트 게임(난이도: 하)
카카오톡에 뜬 네 번째 별! 심심할 땐? 카카오톡 게임별~
카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.
- 다트 게임은 총 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
입출력 예제
생각해보기
가장 먼저 떠오른 생각은 앞에서 부터 한글자씩 받아서 처리하는 것이였습니다.
한글자씩 받아서 해당 글자의 의미에 따라서 처리하면되지만, "*"의 경우 이전의 값도 2배 해주어야 합니다.
따라서 이전의 값을 불러와서 2배를 해줄 수( 값을 변경할수 있게) 있어야 합니다.
3가지 옵션을 생각해보았습니다.
- temp와 prev를 둡니다.
- 배열을 array[3]으로 생성한다.
- 이전의 값만 필요하므로 LIFO인 stack을 사용한다.
우선 1번의 경우 다음숫자가 나오면 현재숫자(temp)를 prev에 넣고, 다음숫자를 temp에 넣는 방식으로 생각해보았습니다. "*"이 나오면 prev와 temp를 2배 해주고 result에 덧셈해주는 것입니다. 하지만, temp는 다음 회차에서 "*"이 나올수 있으므로 바로 더해주지 않습니다. prev만 더해줍니다. prev만 더해주면 3번째 다트점수는 prev에 들어갈수 없기 때문에(다음숫자가 나오지 않기 때문), 추가적인 장치가 필요합니다.
2번의 경우 지금던진 점수가 몇회차의 점수인지 알고있어야 합니다. 3회차에 "*"이 나오면 2회차에 있는 점수를 변경해야 하기 때문입니다.
3번의 경우에는 지금이 몇회차의 점수인지 몰라도 됩니다. 이전의 점수를 변경하려면 pop 하고 값을 변경후 다시 push해주면 됩니다.
2번과 3번에서 사이에서 고민했습니다. 2번의 경우 몇회차인지 카운트하기위한 변수가 1개 더필요하고, 3번의 경우 점수를 변경하기 위해서는 pop과 push를 해주어야 합니다. 이문제의 경우 변수 1개를 더 주는것이 훨씬 간단할거라 판단해서 2번의 방식을 사용하겠습니다.
최종적 과정은 아래와 같습니다.
코딩
이전과 마찬가지로 입력은 main에서 받아주고, 연산은 score함수에서 처리하겠습니다.
해당 문제에서 3번의 게임을 하므로 array의 크기를 3으로 하여 만들어 주어야합니다.
하지만 array[3]으로 선언하게되면, 배열의 크기를 늘리거나 줄일경우 다른부분도 수정해야하므로, 수정하기 쉽게 하기 위해 const(상수)로 배열의 크기를 정해 줍니다. 상수의 값만 바꿔주게되면 몇번의 게임이든 변경하기 쉬워집니다.
https://hwanschoi.tistory.com/56
define은 선행처리자가 처리하고, const는 컴파일러가 처리합니다. define으로 처리하게되면 심볼테이블에 포합되지 않으므로 디버거에서 이름을 가지고 참조 하기 어려워 집니다. 또, const를 사용하면 상수의 타입을 정의할수 있으므로, define보다는 const를 이용하여 상수를 선언해주겠습니다.
한글자씩 읽어와 숫자이면 array에 저장하여주고, 숫자가 아니라면 각 의미에 맞게 처리해주면 됩니다. if else 로 적는것보다는 switch문을 사용하는것이 가독성이 좋으므로, switch문을 사용하여 줍니다.
이것이 기본틀 입니다.
차례대로 하나씩 채워보겠습니다.
우선 숫자이면 array에 넣어주어야 합니다. 또한 몇번째 게임인지 세아리기 위한 변수 temp값도 여기서 변경해주어야 합니다. 값을 넣고 temp++ 해줄지, temp++후 값을 넣어줄지 생각해보아야 합니다. 값을넣고 temp++ 해주게 되면 뒤에 나오는 D,T,*,#에서 temp를 그대로 사용할수 없습니다. 따라서 temp++후 값을 넣어주는것이 맞는 순서입니다. array는 0부터 시작되니 temp는 -1로 초기화후 사용하면 적당할 것 같습니다.
S의 경우에는 따로 처리를 해줄필요가 없습니다. 아무런 변경사항이 없습니다.
D의 경우에는 거듭제곱을 해주어야 합니다. 아무생각없이 "^" 를 사용하였는데, 이는 비트연산자 XOR이므로 주의 하셔야 합니다. c++의 경우 거듭제곱을 위해 pow함수가 존재합니다. pow는 double의 결과가 나오므로 int로 형변환 해주어야합니다.
"*"은 이전의 값과 현재의 값을 2배해주므로, 이전의 값이 없는 temp == 0 인 상황에 주의 하며 2배 해주어야합니다.
"#"은 -1을 곱해주면 됩니다.
다 끝난것같지만 숫자를 array에
이런식으로 넣어주면 안됩니다. input[i]에는 "1"이라는 값이 들어있고 이를 int로 형변환 하여도 아스키 코드값이 나오게됩니다.
https://stackoverflow.com/questions/5029840/convert-char-to-int-in-c-and-c
아스키 코드에서 숫자는 연속적인 값을 가지므로 "0"을 빼주어 int값으로 변환하여 주면 원하던 결과를 얻을수있습니다.
또 한가지 문제가 있습니다.
해당문제에서는 10이라는 점수도 존재합니다. 한글자씩 잘라서 읽기에 이점을 주의해야합니다.
해결방법으로,
- '1'다음 '0'이면 10을 array[temp]에 추가.
- 숫자가 아닌것(S, D, T, *, #)이 나올때까지 읽는다.
여기서 1번 방법은 이문제를 해결하기엔 괜찮은 방법이지만, 점수가 11점이 생기면 또 바꿔주어야하는 불편함이 있습니다. 따라서 변경이 용이한 2번방법으로 해결하겠습니다.
숫자가 나왔고 다음문자가 숫자이면, 이전에 저장한값에 10을 곱해주고, 현재 값을 더해주는 방식으로 해결하였습니다. 이를 다음문자가 숫자가 아닐때까지 반복하면 됩니다.
처음에 만들때 변경이 용이하도록 const를 사용하여 배열의 길이를 정하였으므로, 결과를 만들때도 for문을 사용하여 array의 값들을 더해줍니다.
코드
https://github.com/psg2021/KAKAOtest/blob/master/2018_1st/2018_1st/DartGame.cpp
후기
어우.. github 프로필 사진을 바꾸던가 해야지 매번 얼굴이 너무 당당하게있으니 부담스럽다..
이번 문제는 너무 한가지 예제만 생각하다보니, 문제조건을 잊어버리고 1~9점까지의 점수만 있는줄 알았다.
10점 이상의 점수를 처리하는 부분을 나중에 추가하였다.
조건에 대해 항상 생각하면서 코딩을 해야겠다.
'카카오 코딩테스트' 카테고리의 다른 글
2018 카카오 코딩테스트 - 캐시 (0) | 2019.09.06 |
---|---|
2018 카카오 코딩테스트 - 비밀지도 (0) | 2019.09.03 |