본문 바로가기

개발/Algorithm

[Algorithm] 백준 BOJ 2930 가위바위보 python 파이썬 그리디 브론즈 2

Private 난이도 : ♥♥♥♡♡
 

2930번: 가위 바위 보

가위 바위 보는 두 사람이 즐기는 유명한 게임이다. 각 플레이어는 자신의 손을 이용해서 가위, 바위, 보 중 한 모양을 만들어야 한다. 두 플레이어가 같은 모양을 만든 경우에는 비기게 된다. 가

www.acmicpc.net

import sys

r=int(sys.stdin.readline()) # round 수=5
sg=sys.stdin.readline().strip() # 상근이의 모양
n=int(sys.stdin.readline())  # 친구의 수
play=['' for _ in range(n)]
for i in range(n):
    play[i]=sys.stdin.readline().strip()
    # print(play) #['PPRRS', 'RRSSP']
result=0 # 상근이의 점수

result_dict=dict(RR=1,SS=1,PP=1, RS=2,PR=2,SP=2, SR=0,RP=0,PS=0)
max_rsp=[[[0,0,0] for _ in range(n)]for x in range(r)] # R, S ,P #Rock을 냈을 때 점수,scissor을 냈을 때,, 점수를 저장할 곳
# print(max_rsp) (3,2,5)=(rsp,n,r)
# [[[0, 0, 0], [0, 0, 0]],
#  [[0, 0, 0], [0, 0, 0]],
#  [[0, 0, 0], [0, 0, 0]],
#  [[0, 0, 0], [0, 0, 0]],
#  [[0, 0, 0], [0, 0, 0]]]

for i,s in enumerate(play): #(play) #['PPRRS', 'RRSSP']
    for j,c in enumerate(s): #round 마다
        result += result_dict[sg[j]+c]
        max_rsp[j][i][0] += result_dict['R' + c]
        max_rsp[j][i][1] += result_dict['S' + c]
        max_rsp[j][i][2] += result_dict['P' + c]
# print(max_rsp)
# [[[0, 2, 1], [1, 0, 2]],
#  [[0, 2, 1], [1, 0, 2]],
#  [[1, 0, 2], [2, 1, 0]],
#  [[1, 0, 2], [2, 1, 0]],
#  [[2, 1, 0], [0, 2, 1]]]

max_result=0 #최대 점수
for i in range(r):
    # print(i,max_rsp[i]) # 0 [[0, 2, 1], [1, 0, 2]]
    round_max = [0, 0, 0]
    for j in range(n):
        # print(j , max_rsp[i][j]) # 0 [0, 2, 1] 1 [1, 0, 2]
        for t in range(3):
            round_max[t]+=max_rsp[i][j][t]
            # print(max_rsp[i][j][t])
    max_result+=max(round_max)

print('상근이 점수', result)
print('최대 점수',max_result)

이건 내가 코드를 짜며 설명을 넣은 버전이고, 제출한 코드는 링크에 넣어두었다.

 

설명

  • result_dict
    result_dict=dict(RR=1,SS=1,PP=1, RS=2,PR=2,SP=2, SR=0,RP=0,PS=0)

    이미 그 가위바위보 결과에 대한 점수를 dictionary로 만들어두ㅇㅇ어서 계산을 줄이고자 했다. 경우의 수가 9개밖에 없어서 다행이지;; 아니었으면 좀 더 복잡했을 것 같다.

 

  • result_dict
    max_rsp[j][i][0] += result_dict['R' + c]
    max_rsp[j][i][1] += result_dict['S' + c]
    max_rsp[j][i][2] += result_dict['P' + c]
    각각의 경우를 미리 지정해서 값을 구했다.맨 위의 줄을 설명하면, 상우가 R을 냈다고 가정했을 때 한 친구와 해당 라운드에서 시합하는 것이다. 그렇게 가위, 바위, 보 모든 경우를 계산해서 더했다.

 

기타 배운 점

  • string 을 읽어오면 마지막에 개행이 남아있다.
    상근이의 모양을 출력했는데
    for i,s in enumerate(sg):
        print(i,s)
        
    >>>0 S
    1 S
    2 P
    3 P
    4 R
    5
    IndexError: list index out of range
    에러가 떴다. 마지막에 'SSPPR\n'이 있는 것 같다.
    .strip()으로 지울 수 있다.
    sg=sg.strip()
    근데 개행이 이렇게 에러를 겪지 않고 들어있는지 알 수 있는 방법은 모르겠다.
  • dictionary 사용법
    항상 쓸 때 찾고 잊어버리는,,
    • 값 변경
      dict[key]=변경하고싶은 값
    • 값들만 받기
      dict.values()
  • dictionary의 최대값을 가진 key 찾기
    max(r, key=r.get)
    #출처 : https://bio-info.tistory.com/40

    max의 좋은 사용법,,
  • 컴파일에러
    2번이나 냈는데 둘 다 컴파일 에러 뜨길래 새로운 파이썬 파일로 파이참에서 열어서 확인했는데 괄호 하나가 부족했다,, 마지막에 주석 정리하다가 같이 지워졌나보다
  • 두 리스트간의 합
    list comprehension을 쓰면 쉽다. 이 문제에서는 두 리스트가 아니라 여러 리스트(내가 푼 방식으로는 친구 수 마다 생겼음)에서 각 자리의 합을 하고싶었는데, 생각보다 이게 어려웠다. 3차원으로 가니까 더 노답이었다. 시간복잡도 O(n^3)은 안하고 싶었는데,, 
    sum_list=[x+y for x,y in zip(list1,list2)]
    알고리즘 문제를 너무 오랜만에 풀다 보니 이런 것도 잊어버렸다. 아직도 3차원 리스트의 성분합은 numpy 말고는 반복문 밖에 생각나지 않는다.
  • 최댓값의 index
    list.index(max(list))
     사실 이건 max값이 같은게 2개 있다면 앞에서부터 탐색하는 거라서 같은 최댓값을 가진 모든 인덱스를 다 볼 수는 없다.