Programmers, 월간 코드 챌린지 시즌2, 스택, ‘괄호 회전하기’
프로그래머스 월간 코드 챌린지 시즌2 문제 중 76502번 ‘괄호 회전하기’
https://school.programmers.co.kr/learn/courses/30/lessons/76502?language=python3
문제 설명
다음 규칙을 지키는 문자열을 올바른 괄호 문자열이라고 정의합니다.
- (), [], {} 는 모두 올바른 괄호 문자열입니다.
- 만약 A가 올바른 괄호 문자열이라면, (A), [A], {A} 도 올바른 괄호 문자열입니다. 예를 들어, [] 가 올바른 괄호 문자열이므로, ([]) 도 올바른 괄호 문자열입니다.
- 만약 A, B가 올바른 괄호 문자열이라면, AB 도 올바른 괄호 문자열입니다. 예를 들어, {} 와 ([]) 가 올바른 괄호 문자열이므로, {}([]) 도 올바른 괄호 문자열입니다.
대괄호, 중괄호, 그리고 소괄호로 이루어진 문자열 s가 매개변수로 주어집니다. 이 s를 왼쪽으로 x (0 ≤ x < (s의 길이)) 칸만큼 회전시켰을 때 s가 올바른 괄호 문자열이 되게 하는 x의 개수를 return 하도록 solution 함수를 완성해주세요.
제한사항
- s의 길이는 1 이상 1,000 이하입니다.
입출력 예
|s|result| |:-:|:-:| |”{}”|3| |”}]()[{“|2| |”[)(]”|0| |”}}}”|0|
입출력 설명 에
입출력 예 #1
x | s를 왼쪽으로 x칸만큼 회전 | 올바른 괄호 문자열? |
---|---|---|
0 | ”{}” | O |
1 | ”](){}[” | X |
2 | ”(){}[]” | O |
3 | ”){}[](“ | X |
4 | ”{}” | O |
5 | ”}{“ | X |
- 올바른 괄호 문자열이 되는 x가 3개이므로, 3을 return 해야 합니다.
입출력 예 #2
- 다음 표는 “}]()[{“ 를 회전시킨 모습을 나타낸 것입니다.
x | s를 왼쪽으로 x칸만큼 회전 | 올바른 괄호 문자열? |
---|---|---|
0 | ”}]()[{“ | X |
1 | ”]()[{}” | X |
2 | ”()[{}]” | O |
3 | ”)[{}](“ | X |
4 | ”{}” | O |
5 | ”{}]()[” | X |
- 올바른 괄호 문자열이 되는 x가 2개이므로, 2를 return 해야 합니다.
입출력 예 #3
- s를 어떻게 회전하더라도 올바른 괄호 문자열을 만들 수 없으므로, 0을 return 해야 합니다.
입출력 예 #4
- s를 어떻게 회전하더라도 올바른 괄호 문자열을 만들 수 없으므로, 0을 return 해야 합니다.
풀이
올바른 괄호인지 검사하는 is_valid 함수로 구현했고, 괄호가 회전하는 부분은 슬라이싱을 활용해 구현해 주었다.
- is_valid 함수
- 문자열을 입력받고, 입력받은 문자열 strings의 처음 시작이 닫힌 괄호거나 마지막 끝이 열린 괄호라면 조기종료를 해준다.
- strings를 왼쪽부터 접근하기위해 deque 자료형을 d와 괄호검사를 위한 스택 tmp를 선언한다.
- d의 원소를 모두 검사할때까지 반복을 하는데, [’[’, ‘{‘, ‘(‘] 안에 d[0]가 있다면 바로 tmp에 d.popleft를 활용해 추가해준다.
- d[0]가 [’[’, ‘{‘, ‘(‘]에 존재하지 않는데, tmp가 비어 있다면 유효한 괄호가 아니므로 return False로 검사를 종료한다.
- d[0]가 [’[’, ‘{‘, ‘(‘]에 존재하지 않고, tmp가 비어있지 않다면 tmp[-1]와 d[0]로 괄호가 완성되는지 검사하고, 완성되지 않는다면 return False로 검사를 종료한다.
- 모든 d를 검사하는 동안 종료되지 않았다면 return True로 검사를 종료한다.
- s[i:] + s[0:i]를 활용해 회전 구현
- 슬라이싱 s[i:] + s[0:i]을 통해 회전을 구현 해준다.
- (0 ≤ x < (s의 길이)) 모두를 조사야 하므로 for 문을 통해 모든 x에 대해 검사를 진행한다.
- is_valid 함수가 True라면 answer을 증가시킨다.
from collections import deque, defaultdict
def solution(s):
def is_valid(strings):
print(f'shifted strings: {strings}')
# 조기 종료 조건
if strings[0] in [']', '}', ')']:
return False
if strings[-1] in ['[', '{', '(']:
return False
d = deque(strings)
tmp = []
while d:
# d[0]이 열린 괄호라면 tmp에 넣고 아니라면 다음 조건을 진행
if d[0] in ['[', '{', '(']:
tmp.append(d.popleft())
# d[0]가 닫힌 괄호면서 tmp가 비었다면 조기종료
elif not tmp:
return False
# d[0]와 tmp[-1] 비교를 통해 유효한 괄호인지 검사
elif d[0] == ']':
if tmp[-1] == '[':
tmp.pop()
d.popleft()
else:
return False
elif d[0] == '}':
if tmp[-1] == '{':
tmp.pop()
d.popleft()
else:
return False
else:
if tmp[-1] == '(':
tmp.pop()
d.popleft()
else:
return False
# 반복이 종료된다면 유효한 괄호이다.
return True
n = len(s)
answer = 0
# 입력으로 주어진 문자열이 홀수라면 조기종료
if n % 2 != 0:
return 0
for i in range(n - 1):
if is_valid(s[i:] + s[0:i]):
answer += 1
return answer
print(f'answer: {solution("}]()[{")}')
shifted strings: }]()[{
shifted strings: ]()[{}
shifted strings: ()[{}]
shifted strings: )[{}](
shifted strings: [{}]()
answer: 2
Leave a comment