논리적으로 차분하게 코딩하기
1. 문제
https://programmers.co.kr/learn/courses/30/lessons/17682
카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다.
다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심부분인 점수 계산 로직을 맡게 되었다.
다트 게임의 점수 계산 로직은 아래와 같다
다트 게임은 총 3번의 기회로 구성된다
각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨시 점수에서 1제곱,2제곱,3제곱으로 계산된다
옵션으로 스타상(*), 아차상(#)이 존재하며 스타상 당첨시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다.
아차상 당첨시 해당 점수는 마이너스된다.
스타상은 첫번째 기회에서도 나올 수 있다. 이 경우 첫번째 스타상의 점수만 2배가 된다.
스타상의 효과는 다른 스타상의 효과와 중첩될 수 있다.
이 경우 중첩된 스타상 점수는 4배가 된다.
스타상의 효과는 아차상의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상의 점수는 -2배가 된다
Single(S), Double(D), Triple(T)는 점수마다 하나씩 존재한다
스타상,아차상은 점수마다 둘 중 하나만 존재할 수 있으며 존재하지 않을 수도 있다
0~10의 정수와 문자 S,D,T,*,#로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하세요
2. 예시
3. 나의 풀이
기술은 필요하지 않고 규칙에 맞게 침착하게 코딩하면 된다
def solution(dartResult):
answer = 0
score_list = []
for ind, result in enumerate(dartResult):
if result.isdigit():
if ind >= 1:
if result == '0':
if score_list[-1] == 1:
score_list[-1] = 10
else:
score_list.append(int(result))
else:
score_list.append(int(result))
else:
score_list.append(int(result))
숫자, 문자 이런식으로 구성되어 있으니까 dartResult에서 문자를 하나씩 빼서 숫자인지 문자인지 검사를 하는 isdigit()을 사용
숫자라면 이제 score_list에 넣으면 되는데 문자니까.. int로 바꿔서 넣어준다
근데 이제 10이 문제인데.. 10을 넣기 위해서 enumerate()로 ind까지 빼줄건데
ind가 1이상인경우는.. dartResult에서 뺀 문자 result가 ‘0’이면…
이제 score_list에 마지막으로 들어간 숫자가 1인지 아닌지 검사를 한다
1이라면 10이 들어가야하므로 마지막에 들어간 숫자를 10으로 수정하고
1이 아니면 그냥 0을 int로 바꿔서 넣어준다
else:
if result == 'S':
score_list[-1] = score_list[-1] ** 1
elif result == 'D':
score_list[-1] = score_list[-1] ** 2
elif result == 'T':
score_list[-1] = score_list[-1] ** 3
elif result == '*':
if len(score_list) == 1:
score_list[-1] = score_list[-1] * 2
else:
score_list[-2] = score_list[-2] * 2
score_list[-1] = score_list[-1] * 2
else:
score_list[-1] = score_list[-1] * (-1)
answer = sum(score_list)
return answer
이제 문자에 따른 효과를 구성할건데
result가 S,D,T인 경우 바로 앞의 숫자에 대해 1제곱,2제곱,3제곱을 할건데
이제 만약 문자로 S,D,T가 나온다면 그 전 문자는 숫자이고 score_list에 들어갔을거임
마지막에 score_list로 들어간 score_list[-1]에 효과가 적용된다는 소리
근데 이제 *랑 # 이게 문제인데
*인 경우는 *앞에 붙은 score인 score_list[-1]에 적용이 되어야하는데
문제는 *앞에 붙은 것 뿐만 아니라 그 이전 score인 score_list[-2]에도 적용이 되어야한다
더 생각을 해서 *이 첫번째에 나오냐, 두번째에 나오냐 다를 수 있음
score_list의 길이가 1인지 아닌지 검사해서 1이면 *이 첫번째에 나온 것이므로
score_list[-1]에만 적용하고 1이 아니면 *이 두번째 이후에 나온거라서 [-2]와 [-1]모두에 2배를 적용
마지막으로 #이 나오면 그 앞에 나온 숫자에 -1배를 해야해서 score_list[-1] -1을 곱해준다
최종적으로 반복문을 끝내면 score_list의 합을 구한다
4. 다른 풀이
10을 어떻게 처리했을지..? 주목해볼 필요가 있다
def solution(dartResult):
point = []
answer = []
dartResult = dartResult.replace('10','k')
point = ['10' if i == 'k' else i for i in dartResult]
dartResult에서 ‘10’이 존재하면 ‘k’라는 문자로 바꿔주고
point라는 리스트를 만드는데 ‘k’이면 10으로 바꿔서 넣어줘
i = -1
sdt = ['S','D','T']
for j in point:
if j in sdt:
answer[i] = answer[i] ** (sdt.index(j)+1)
elif j == '*':
answer[i] = answer[i] * 2
if i != 0:
answer[i-1] = answer[i-1] * 2
elif j == '#':
answer[i] = answer[i] * (-1)
else:
answer.append(int(j))
i += 1
return sum(answer)
다음 sdt를 구성한 다음에 i=-1로 초기화하고
point에는 숫자, 문자가 구성된 리스트일텐데 for문으로 돌아
처음 돌 때는 문자일리 없으니까 마지막 else문에서 answer.append(int(j))에 들어갈거고
이제 i를 +=1을 해주는데
그러면 answer에 마지막으로 들어간 수는 index 0에 저장이 되어 있을거
이제 문자가 나올텐데 만약 S,D,T이면 1제곱 2제곱 3제곱을 할건데
if문으로 S,D,T로 안나누고 sdt.index를 이용해서 한문장으로 처리한거 멋지고
만약 *가 나온다면 2배를 할건데
숫자가 들어갈 때마다 i에 값이 더해지니까
i가 0이 아니라면.. 그러니까 i가 1이나 2라면 answer에 숫자가 2개 이상 들어가있으니까
answer[i]와 answer[i-1] 모두에 2배를 하고 i가 0이면 answer에 숫자 하나가 들어가있으니까 answer[i]만 2배를함
#이면 마지막으로 들어간 answer[i]에 -1배를 함
한번의 for문을 다 돌면 answer에 들어간 점수의 합을 return
5. 되돌아보기
이런 문제는 알고리즘 기술이 안들어가서 쉽지만 문제 조건에 맞게 논리적으로 코딩을 잘 해야한다
10을 어떻게 처리했는지? 다른 풀이에서 replace를 이용해서 문자 하나로 바꿔서 처리한거 멋지고
물론 나도 복잡했지만 논리적으로 처리 잘 했다
마지막으로 들어간 수 score_list[-1]을 활용 잘 했다는 점
*의 효과를 처리할 때 첫번째로 들어가냐, 두번째로 들어가냐 경우를 잘 생각했고
S,D,T의 점수 처리할때 if문 3개로 나눠서 하느냐…
아니면 그냥 리스트에 넣어서 index를 활용해서 if 한문장으로 처리하느냐..?
'알고리즘 > 알고리즘 일반' 카테고리의 다른 글
오름차순 배열과 내림차순 배열을 동시에 적용하는 방법? (0) | 2022.01.03 |
---|---|
선형구조와 비선형구조 (0) | 2022.01.02 |
다양한 피보나치 수열 알고리즘 (0) | 2022.01.01 |
반복문에서 경우의 수를 나누는 방법 (0) | 2021.11.28 |
stack 필수 활용 기술 3 (0) | 2021.11.27 |