33167번 - じゃんけん (Rock-Scissors-Paper)
가위바위보 (Rock-Scissors-Paper)
길이 N의 문자열 S, T가 주어진다. S의 각 문자는 R 또는 S 중 하나이다. T의 각 문자는 R 또는 P 중 하나이다.
아오이와 비타로는 N번의 가위바위보를 했다. 아오이가 i번째(1 ≤ i ≤ N) 가위바위보에서 낸 것은 S의 i번째 문자가 R일 때는 바위, S일 때는 가위이다. 비타로가 i번째(1 ≤ i ≤ N) 가위바위보에서 낸 것은 T의 i번째 문자가 R일 때는 바위, P일 때는 보이다.
전체 N번의 가위바위보에서 아오이가 이긴 횟수와 비타로가 이긴 횟수를 구하시오.
입력
입력은 다음 형식으로 주어진다.
N
S
T
출력
전체 N번의 가위바위보에서 아오이가 이긴 횟수와 비타로가 이긴 횟수를 단위(회)를 제외하고 공백으로 구분하여 출력하시오.
정답 이외에는 아무것도 출력하지 마시오. (입력을 유도하는 문장 등도 출력하지 마시오.)
제한
1 ≤ N ≤ 100 | N은 정수이다. |
S는 길이 N의 문자열이다. | S의 각 문자는 R 또는 S 중 하나이다. |
T는 길이 N의 문자열이다. | T의 각 문자는 R 또는 P 중 하나이다. |
예제 입력 1
3
RSR
PPR
1 1
1번째 가위바위보에서 아오이는 바위를 냈고, 비타로는 보를 냈다. 따라서 비타로가 이겼다.
2번째 가위바위보에서 아오이는 가위를 냈고, 비타로는 보를 냈다. 따라서 아오이가 이겼다.
3번째 가위바위보에서 아오이는 바위를 냈고, 비타로는 바위를 냈다. 따라서 비겼다.
아오이와 비타로가 이긴 횟수는 각각 1회와 1회이다. 따라서 1과 1을 공백으로 구분하여 출력한다.
예제 입력 2
5
RRRRR
PPPPP
0 5
모든 가위바위보에서 아오이는 바위를 냈고, 비타로는 보를 냈다. 따라서 모든 가위바위보에서 비타로가 이겼다.
아오이와 비타로가 이긴 횟수는 각각 0회와 5회이다. 따라서 0과 5를 공백으로 구분하여 출력한다.
예제 입력 3
4
RSRR
RPRR
1 0
1번째 가위바위보에서 아오이는 바위를 냈고, 비타로는 바위를 냈다. 따라서 비겼다.
2번째 가위바위보에서 아오이는 가위를 냈고, 비타로는 보를 냈다. 따라서 아오이가 이겼다.
3번째 가위바위보에서 아오이는 바위를 냈고, 비타로는 바위를 냈다. 따라서 비겼다.
4번째 가위바위보에서 아오이는 바위를 냈고, 비타로는 바위를 냈다. 따라서 비겼다.
아오이와 비타로가 이긴 횟수는 각각 1회와 0회이다. 따라서 1과 0을 공백으로 구분하여 출력한다.
예제 입력 4
6
RSSRSS
PPRRRP
2 3
풀이 아이디어
아이디어는 다음과 같이 낼 수 있다.
1. 아오이의 승리 조건과 비타로의 승리 조건을 검사해서 세는 방법(가장 기본적인 방법)
2. 아오이의 승리 조건과 무승부 조건을 검사해서 n에서 빼는 방법
3. 바이트로 읽어와서 두 문자의 차가 어느 집합에 있는지로 카운트하는 방법
4 . 바이트로 읽어와서 두 문자의 차가 아오이의 승리조건인지 0인지 세서 빼는 방법
5. 바이트로 읽어와서 두 문자의 차로 인덱스를 만들어서 리스트에 더하는 방법.
내가 처음 떠올린 방법은 3번이었다.
RSP의 아스키 코드를 보면 R은 82, S는 83, P는 80이다. 이를 이용하면 두 문자의 차이를 계산해 승패를 결정할 수 있다.
아오이가 R(바위)일 때 비타로가 P(보)면 차이는 R-P = 82-80 = 2가 된다. 이 경우 비타로가 이긴다.
아오이가 S(가위)일 때 비타로가 R(바위)면 차이는 S-R = 83-82 = 1이 된다. 이 경우 비타로가 이긴다.
아오이가 S(가위)일 때 비타로가 P(보)면 차이는 S-P = 83-80 = 3이 된다. 이 경우 아오이가 이긴다.
아오이가 R(바위)일 때 비타로가 R(바위)면 차이는 R-R = 82-82 = 0이 된다. 이 경우 무승부다.
이러한 아스키 코드 차이를 이용해 승패를 결정하고 카운트할 수 있다. 승패표를 만들어서 각 차이값에 따른 결과를 미리 정의해두고, 문자열을 순회하면서 결과를 누적하는 방식으로 문제를 효율적으로 해결할 수 있다.
A - B | 아오이 | |||
S(83) | R(82) | P(80) | ||
비 타 로 |
S(83) | 0 | -1 | -3 |
R(82) | 1 | 0 | -2 | |
P(80) | 3 | 2 | 0 |
- 아오이의 승리조건 집합 {-1, -2, 3}
- 비타로의 승리조건 집합 {1, 2, -3}
- 무승부 {0}
n,a,b=open(0,'rb').read().split()
aw={-1,3,-2}
bw={1,-3,2}
res=[0,0]
for i,j in zip(a,b):
res[0]+=i-j in aw
res[1]+=i-j in bw
print(*res)
그런데 이 숫자들을 가만히 보니 길이 7짜리 리스트의 인덱스였다.
D:무승부, A:아오이 승, B:비타로 승이라고 하면, 인덱스가 가리키는 자리는
분류 | D | B | B | A | B | A | A |
결과 | 0 | 1 | 2 | 3 | -3 | -2 | -1 |
인덱스 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
그래서 길이 7의 리스트에 A-B인덱스를 +1 하면 아무 조건 검사 없이 카운팅 할 수 있다. 심지어 무엇으로 이겼는지도 남기면서 무승부도 세면서 더 빠르게 계산이 가능하다.
n,a,b=open(0,'rb').read().split()
r=[0]*7
for i,j in zip(a,b):
r[i-j]+=1
print(r[6]+r[3]+r[5],r[1]+r[4]+r[2])
혹은,
n,a,b=open(0,'rb').read().split()
r=[0]*7
for i in range(int(n)):
r[a[i]-b[i]]+=1
print(r[6]+r[3]+r[5],r[1]+r[4]+r[2])
https://www.youtube.com/shorts/aVGM_hP9mPw?feature=share
