코딩테스트문제, 다트게임 구현하기
코딩테스트문제, 다트게임 구현하기 — #코딩테스트문제 #다트게임 #개발자의도구들 AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작성...
#코딩테스트문제 #다트게임 #개발자의도구들
AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작성하였습니다.
\본 게시글은 PC버전에 최적화되어있습니다.\
다트게임
파이썬으로
문제
| 💡 카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.다트 게임은 총 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, \, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라. |
|---|
| 예제 | dartResult | answer | 설명 |
|---|---|---|---|
| 1 | 1S2D\*3T | 37 | 1^1 \ 2 + 2^2 \ 2 + 3^3 |
| 2 | 1D2S#10S | 9 | 1^2 + 2^1 \* (-1) + 10^1 |
| 3 | 1D2S0T | 3 | 1^2 + 2^1 + 0^3 |
| 4 | 1S*\**2T\*3S | 23 | 1^1 \ 2 \ 2 + 2^3 \* 2 + 3^1 |
| 5 | 1D#2S\*3S | 5 | 1^2 \ (-1) \ 2 + 2^1 \* 2 + 3^1 |
| 6 | 1T2D3D# | -4 | 1^3 + 2^2 + 3^2 \* (-1) |
| 7 | 1D2S3T\* | 59 | 1^2 + 2^1 \ 2 + 3^3 \ 2 |
| ⌨️ 입력: "점수|보너스|\[옵션\]"으로 이루어진 문자열 3세트. |
|---|
| 🖨 출력: 3번의 기회에서 얻은 점수 합계에 해당하는 정수값을 출력한다. |
|---|
문제풀이
어떤 자료구조를 사용할 것인가?
입력으로는 문자열이 들어오는데, 각 문자열을 숫자영역/문자영역/보너스 별로 분류를 해야합니다.
반복문을 사용하여 문자열 하나 하나를 읽어가며 분류를 하면 될 것 같습니다.
분류된 각 점수는 각각 리스트로 넣어 마지막에 리스트에서 출력하여 더해주면 될 것 같습니다.
나머지 추가적인 부분은 코드를 작성해가며, 그때 그때 두현하도록 해보겠습니다.
점수를 입력받고 분류하기
| points = input() numList = \[\]charList = \[\]bonusList = \[\]for point in points: if "1" <= point <= "9": point = int(point) numList.append(point) else: if point == "S": charList.append(1) bonusList.append(1) elif point == "D": charList.append(2) bonusList.append(1) elif point == "T": charList.append(3) bonusList.append(1) else: if point == "\": bonusList.append(bonusList.pop() \ 2) elif point == "#": bonusList.append(bonusList.pop() \* -1) |
|---|
points는 1D2T3D\* 형태로 분류가 가능합니다. 우선 숫자 check해주고 맞는 경우 point에 해당하는 숫자만큼 numList에 넣습니다.
숫자가 아닐경우 문자인지 체크하며 문자인 경우 S,D,T에 따라 1, 2, 3을 charList에 넣어줍니다. 추가적으로 문자가 끝나면 한 게임 셋이 끝난걸로 간주되어 bonusList에 1을 넣어주겠습니다.
마지막으로 보너스 포인트에 해당하는 문자열을 분류합니다. 위에 문자 분류가 끝남에 따라 bonusList에 1이 들어있기 때문에, 해당 값을 pop()으로 호출 후 \*인 경우 2를 , #인 경우 -1을 곱하여 다시 넣어줍니다.
테스트
실행 후 아래 값을 입력한 결과
| 2D\*3D8T# |
|---|
| numList = \[2, 3, 8\] charList = \[2, 2, 3\] bonusList =\[2, 1, -1\] |
|---|
반복문을 활용하여 numList\[i\] \\ charList\[i\] \* bonusList로 값을 구하는 전략을 사용합니다.
10점 처리
아직 완벽하게 구현된건 아닙니다. 예외처리 몇가지가 남아있기 때문인데요. 가장 첫번째로 예외처리할 부분은 10점처리입니다.
10점 처리는 replace를 통해 구현하였습니다.
| points = input()points = points.replace("10", ".") |
|---|
10점이 들어가면 자동으로 "."으로 변환됩니다. 이제 "." 인경우 numList에 10을 추가하는 코드를 작성해줘야 겠죠?
| for point in points:if "0" <= point <= "9": point = int(point) numList.append(point)elif point == "." numList.append(10) |
|---|
테스트
10점인 경우를 테스트 해봅시다.
| 10S10D10T |
|---|
| .S.D.TnumList = \[10, 10, 10\] |
|---|
numList에 10이 모두 들어와있는걸 보실 수 있습니다.
스타상 예외처리
문제에 스타상에 대한 예외처리가 추가로 있습니다. 바로 이부분인데요.
| 1. 스타상(\)의 효과는 다른 스타상(\)의 효과와 중첩될 수 있다. 이 경우 중첩된 스타상(\) 점수는 4배가 된다. (예제 4번 참고)2. 스타상(\)의 효과는 아차상(#)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(#)의 점수는 -2배가 된다. (예제 5번 참고) |
|---|
예를들어 2D\3D\1T\의 경우 앞의 2^2 \ 2(원래 스타상) \ 2(중첩 스타상) + 3^2 \ 2(원래 스타상) \ 2(중첩스타상) + 1^3 \ 2(원래 스타상)으로 계산됩니다.
식이 좀 복잡한데, 쉽게 말하면 스타상은 중첩되는데, 자신의 바로 앞의 보너스 점수에만 영향을 미친다고 기억하시면 될 것 같습니다.
스타상 예외 떄문에 bonusList를 다시 구현해야 할 것 같습니다. 함꼐 구현해봅시다.
| else: if point == "\": bonusList.append(bonusList.pop() \ 2) ~~ ~~~~if ~~~~len~~~~(bonusList) > ~~~~1~~~~:~~~~ sec\_bonus = bonusList.pop()~~~~ fst\_bonus = bonusList.pop() ~~~~ ~~~~if ~~~~fst\_bonus != ~~~~1~~~~:~~~~ bonusList.append(fst\_bonus \ ~~~~2~~~~)~~~~ bonusList.append(sec\_bonus)~~ ~~ ~~~~else~~~~:~~~~ bonusList.append(fst\_bonus)~~~~ bonusList.append(sec\_bonus)~~~~~~ elif point == "#": bonusList.append(bonusList.pop() \ -1) |
|---|
중첩은 스타상(\*)효과만 된다고 했으니, 스타상 부분 코드만 바꿔주면 되겠습니다. 우선 이전 bonus결과를 가져와야하는데, 첫번째로 보너스가 만들어진 경우 이전값이 없기 때문에 예외처리를 해줘야 합니다.
~~ 두번째 보너스부터 이전값까지 pop()시켜 뽑아낸 후 fst\_bonus 값이 1인지 아닌지 체크합니다. 1인 경우에는 뽑은걸 그대로 다시 넣어주면 되지만, fst\_bonus가 1이아닌 2 or -1인 경우 값을 2배하여 넣어줍니다.~~
~~~~
문제를 잘 못 이해했습니다. 스타상이 2번째 이후부터 나오면 앞의 보너스 점수 여부와 상관없이 무조건 앞의 점수도 2배가 됩니다. 코드를 수정하였습니다.
| else: if point == "\": bonusList.append(bonusList.pop() \ 2) if len(bonusList) > 1: sec\_bonus = bonusList.pop() fst\_bonus = bonusList.pop() bonusList.append(fst\_bonus \ 2) bonusList.append(sec\_bonus) elif point == "#": bonusList.append(bonusList.pop() \ -1) |
|---|
합 구하기
모든 리스트에 올바르게 값이 분류되었습니다! 마지막으로 반복문을 활용하여 합을 구해주면 끝입니다!
| sum = 0for i in range(3): sum += numList\[i\] \\ charList\[i\] \* bonusList\[i\]print(numList,"\n", charList, "\n", bonusList, "\n")print(sum) |
|---|
