AC
문제 설명
선영이는 주말에 할 일이 없어서 새로운 언어 AC를 만들었다. AC는 정수 배열에 연산을 하기 위해 만든 언어이다. 이 언어에는 두 가지 함수 R(뒤집기)과 D(버리기)가 있다.
함수 R은 배열에 있는 숫자의 순서를 뒤집는 함수이고, D는 첫 번째 숫자를 버리는 함수이다. 배열이 비어있는데 D를 사용한 경우에는 에러가 발생한다.
함수는 조합해서 한 번에 사용할 수 있다. 예를 들어, "AB"는 A를 수행한 다음에 바로 이어서 B를 수행하는 함수이다. 예를 들어, "RDD"는 배열을 뒤집은 다음 처음 두 숫자를 버리는 함수이다.
배열의 초기값과 수행할 함수가 주어졌을 때, 최종 결과를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. T는 최대 100이다.
각 테스트 케이스의 첫째 줄에는 수행할 함수 p가 주어진다. p의 길이는 1보다 크거나 같고, 100,000보다 작거나 같다.
다음 줄에는 배열에 들어있는 수의 개수 n이 주어진다. (0 ≤ n ≤ 100,000)
다음 줄에는 [x1,...,xn]과 같은 형태로 배열에 들어있는 수가 주어진다. (1 ≤ xi ≤ 100)
전체 테스트 케이스에 주어지는 p의 길이의 합과 n의 합은 70만을 넘지 않는다.
출력
각 테스트 케이스에 대해서, 입력으로 주어진 정수 배열에 함수를 수행한 결과를 출력한다. 만약, 에러가 발생한 경우에는 error를 출력한다.
입력 예시
4 RDD 4 [1,2,3,4] DD 1 [42] RRD 6 [1,1,2,3,5,8] D 0 [] |
출력 예시
[2,1] error [1,2,3,5,8] error |
나의 풀이
import sys
from collections import deque
T = int(sys.stdin.readline()) # 테스트케이스 개수
for _ in range(T):
p = sys.stdin.readline().rstrip() # 수행할 함수
n = int(sys.stdin.readline()) # 배열에 들어있는 수의 개수
# 배열 ([1,2,3,4]를 입력으로 받은 것을 리스트에 1, 2, 3, 4로 저장하기)
arr = list(sys.stdin.readline().rstrip().split(','))
arr[0] = arr[0][1:]
arr[n-1] = arr[n-1][:len(arr[n-1])-1]
# 리스트 형식의 arr을 덱 형식으로 변경
arr = deque(arr)
r = 1 # 뒤집기 여부 (r=1이면 앞부터, r=-1이면 뒤부터)
error = 0 # error 발생 여부
# p 하나씩 수행
for fun in p:
if fun == 'R':
r = -r # r=1이면 앞부터(popleft), r=-1이면 뒤부터(pop)
elif fun == 'D':
# 배열이 비어있을때 D를 사용하면 에러
if len(arr) == 0 or arr[0] == '':
error = 1
break
# r=1이면 앞부터(popleft), r=-1이면 뒤부터(pop)
if r == 1:
arr.popleft()
else:
arr.pop()
# r = -1이면 뒤집어서 출력
if r == -1:
arr.reverse()
if error == 1: # error 발생했으면 error 출력
print('error')
else: # 리스트 형식으로 출력 ex)[1,2]
print('[', end='')
print(*arr, sep=',', end=']\n')
- 💡 아이디어
p 내의 함수가 100,000개까지 존재할 수 있지만 시간은 1초이므로, 빠르게 동작하는 덱을 사용했다. 함수가 R이라면 뒤집기를 수행해야하지만, R이 나올 때마다 reverse()를 수행하면 시간이 걸리므로, popleft와 pop만 이용하도록 하였다. r=1로 두고, R이 나오면 r에 (-1)을 곱하여, r이 1이면 앞부분을 제거하는 pop()을 이용하고, r이 -1이면 뒷부분을 제거하는 popleft()를 이용하도록 하였다.
마지막 부분에서만 r이 -1이라면 reverse()를 하여 뒤에서부터 출력하도록 하였다.
- 📚 후기
뒤이어 쓸 것이지만, 이 코드는 세번째 시도한 코드이다. 두번의 코드는 시간초과가 떴다. 처음 코드에서는 덱을 이용하였지만 R이 등장할 때마다 계속 reverse를 수행하여 시간초과가 떴고, 두번째 코드에서는 덱을 사용하지 않고, 리스트를 사용하여 시간초과가 떴다.
- ✏️ 배운점
시간이 부족하다면 덱의 pop, popleft, append, appendleft로만 이용하여 문제를 해결할 수 있는지 생각해보자!
# 시간초과가 뜬 첫번째 코드(실패한 코드)
import sys
from collections import deque
T = int(sys.stdin.readline())
for _ in range(T):
p = sys.stdin.readline().rstrip() # 수행할 함수
n = int(sys.stdin.readline()) # 배열에 들어있는 수의 개수
# 배열 ([1,2,3,4]를 입력으로 받은 것을 리스트에 1, 2, 3, 4로 저장하기)
arr = list(sys.stdin.readline().rstrip().split(','))
arr[0] = arr[0][1:]
arr[n-1] = arr[n-1][:len(arr[n-1])-1]
# 리스트 형식의 arr을 덱 형식으로 변경
arr = deque(arr)
error = 0 # error 발생 여부
for i in range(len(p)):
if p[i:].count('D') > len(arr): # D의 개수가 배열 요소의 개수보다 많다면 error 발생
error = 1
break
if p[i] == 'R': # 함수가 R이라면 reverse
arr.reverse()
if p[i] == 'D': # 함수가 D라면 제거
if len(arr) == 0 or arr[0] == '': # 배열이 비어있을때 D를 사용하면 에러
error = 1
break
else:
arr.popleft()
if error == 1: # error 발생했으면 error 출력
print('error')
else: # 리스트 형식으로 출력 ex)[1,2]
print('[', end='')
print(*arr, sep=',', end=']\n')
# 시간초과가 뜬 두번째 코드(실패한 코드)
import sys
from collections import deque
T = int(sys.stdin.readline())
for _ in range(T):
p = sys.stdin.readline().rstrip() # 수행할 함수
n = int(sys.stdin.readline()) # 배열에 들어있는 수의 개수
# 배열 ([1,2,3,4]를 입력으로 받은 것을 리스트에 1, 2, 3, 4로 저장하기)
arr = list(sys.stdin.readline().rstrip().split(','))
arr[0] = arr[0][1:]
arr[n-1] = arr[n-1][:len(arr[n-1])-1]
# 리스트 형식의 arr을 덱 형식으로 변경
arr = deque(arr)
error = 0 # error 발생 여부
stop = 0
while True:
#print(i)
if p[0:].count('D') > len(arr) or arr[0] == '': # D의 개수가 배열 요소의 개수보다 많다면 error 발생
error = 1
break
# 연속된 R 혹은 연속된 D 개수 세기
# (ex. p가 RRDDD라면 R의 연속 개수 2를 세고 RR삭제, p는 DDD가 됨. 이 후 D의 연속 개수 3 세고 DDD삭제)
cnt = 1
order = p[0]
if order == 'R': # 함수가 R이라면
j = p.find('D') # p 내의 D 중 가장 앞의 index를 구함
else: # 함수가 D라면
j = p.find('R') # p 내의 R 중 가장 앞의 index를 구함
if j == -1: # 함수가 R일 때 p 내에 D, 함수가 D일 때 p 내에 R이 없다면
cnt = len(p) # cnt는 남은 p의 개수
stop = 1 # p를 전부 본 것이므로 멈추기
else:
cnt = j
p = p[j:] # 개수를 센 함수는 삭제
if order == 'R': # 함수가 R이라면
if cnt % 2 == 1: # R의 개수가 홀수일 때만 뒤집기
arr.reverse()
else: # 함수가 D라면
arr = arr[cnt:] # arr의 D의 개수만큼 앞부분 삭제
if stop == 1: # p를 전부 봤다면 멈추기
break
if error == 1: # error 발생했으면 error 출력
print('error')
else: # 리스트 형식으로 출력 ex)[1,2]
print('[', end='')
print(*arr, sep=',', end=']\n')
'Programming > Questions' 카테고리의 다른 글
[백준/Python] 이진탐색 - 공유기 설치(2110) (0) | 2021.08.18 |
---|---|
[백준/Python] 해시 - 임진왜란(3077) (0) | 2021.08.09 |
[백준/Python] 해시 - I AM IRONMAN(17264) (0) | 2021.08.09 |
[백준/Python] 해시 - 나는야 포켓몬 마스터 이다솜(1620) (0) | 2021.07.19 |
[프로그래머스/Python] 해시 - 전화번호 목록 (0) | 2021.07.14 |