
블로그 방문자가 아닌, 나를 위해 정리하는 문제해결 인사이트 정리. 문제 해결에 필요한 지식이나 정보는 검색하면 나오지만 "어떤 식으로 문제에 접근하고 해결하는지 그 태도"는 자기 스스로 발견하는 거니까, 그게 제일 중요한 거니까 정리합시다🔥
예제 문제
https://www.acmicpc.net/problem/9012
9012번: 괄호
괄호 문자열(Parenthesis String, PS)은 두 개의 괄호 기호인 ‘(’ 와 ‘)’ 만으로 구성되어 있는 문자열이다. 그 중에서 괄호의 모양이 바르게 구성된 문자열을 올바른 괄호 문자열(Valid PS, VPS)이라고
www.acmicpc.net
😳지금 보면 별 대단한 문제가 아니지만, 예전에는 이 문제를 어떻게 풀지 참 난감했었던 기억이 있다. 그 시간동안 나름 성장한 바가 있으니 문제를 수월하게 풀 수 있었기 때문에 이 문제를 예시로 들고 왔다.
1. 문제를 읽고 예제의 입출력을 파악한다.
보통 문제들은 추상화되어 있다. 사실 추상화된 문장은 문제를 그럴듯하게 꾸며놓은 것 뿐이지 문제해결에 필요한 핵심은 아니다. 핵심은 문제에서 주어지는 입력변수들이 무엇인지, 서로 어떤 관계인지를 파악하는 것에 있다.

솔직히 맨 먼저 문제만 읽으면 한 번에 잘 안 읽히고, '이게 뭔 소리야,,' 하는 경우가 많다. 그래서 나름대로 문제 파악을 하는 순서를 정리했는데
- 일단 문제를 읽으면서 대충 스토리를 파악한다.
- 입력 / 출력을 보면서 변수들을 파악한다.
- 다시 문제를 보면서 입력 변수가 문제에서 어떻게 표현되고 입력 변수들과 출력이 어떤 관계로 이어져 있는지 본다.
- 코드를 작성하되 입력을 받고 출력을 내뱉는 부분만 일단 작성한다. (파이썬의 경우 sys의 readline을 쓸지 아니면 input을 쓸지 결정, 출력은 print로 하는지 return으로 하는지)
2. 뇌피셜(나의 방식)으로 문제풀기

보통 예제를 보면 확실히 이해 되는 경우가 많다. 예제들을 보면서 문제에서 나뉘는 출력의 케이스들(여기서는 NO,YES)을 서로 비교하며 입력에 어떤 차이가 있는지 본다. 비교할 때는 입력값을 하나씩 떼어보거나, 나눠보는 등 직접 값을 만져가며 이해한다.
위 문제에서는 'YES'의 입력들은 여는 괄호'('와 닫는 괄호')'가 1:1로 매칭되어 개수가 서로 맞아떨어지지만 'No'는 그렇지 않다.
이런 아이디어을 검증하기 위해 다른 예제들에 대해서도 아이디어를 적용하여 최종 검증하고, 다른 예제에서 적용되지 않는다면 그 예제에 비춰 아이디어를 수정한다.
이렇게 머리로 입력값들을 만지면서 문제를 풀면 알고리즘은 어느정도 완성된다.
3. 코드 로직으로 옮기기
지금까지의 과정을 따랐던 실제 작성 코드이다.
# 예제 보면서 패턴 파악
# 정답인 예제와 오답인 예제의 차이 도출하기
# 오답 케이스
# (()) ())
# (() ((()) () (
# (())()))
# (()
# (과 )의 짝이 맞아야 한다
# 정답 케이스
# (()()) ((()))
# () () () () (()()()) ()
# (())()
# ((()))
# 인간 뇌피셜(나의 방식)으로 문제풀기
# 코드 로직으로 옮기기
# (가 나오면 스택으로 쌓는다
# )가 나오기 시작하면 )만 연달아 나와야한다
# 그리고 그 개수가 (가 쌓인 개수와 같아야 한다
# 짝이 맞으면 초기화
# 초기화했는데 (가 아니라 )가 나오면 탈락
import sys
length = int(input())
stack = []
for i in range(length):
elem = list(sys.stdin.readline().strip())
for unit in elem:
if unit == '(':
stack.append('(')
elif unit == ')':
if len(stack) != 0 and stack[-1] == '(':
stack.pop()
elif len(stack) == 0:
stack.append(')')
if len(stack) == 0:
print('YES')
stack = []
else:
print('NO')
stack = []
지금은 코드 제출을 위해 print들을 싹 지웠지만 매 로직(특히 변수에 값 할당)마다 print를 수시로 찍어서 로직이 잘 코드화되는지 확인한다. 수시로 값을 확인하지 않으면 어디서 코드화가 잘 되지 않았는지 헤메기 쉽다.
사실 print만 잘찍어도 못 풀 문제는 없다. 테스트 케이스 하나 하나에 대해 for문, if문, 변수할당만 쭉쭉 작성하면 다 커버할 수 있기 때문이다.
코드화는 알고리즘을 코드로 옮기는 과정인데, 언어에 대한 지식에 굉장히 의존적이라고 생각한다.
"나는 이런 로직을 작성하고 싶은데, 코드로는 어떻게 표현하지?"
파이썬을 문서 먼저 보고 익힌 사람은 없을 것이라고 생각한다. 위와 같이 어떠한 문제를 맞닥뜨리고 검색을 해서 익히는 것이 자연스러운 과정이다. 검색으로 문제를 해결할 때는 이렇게 '코드화'에 대한 지식을 얻어오는 것은 좋은 학습법이 되겠지만, 간혹 '알고리즘'에 대한 지식을 통째로 가져오고 싶은 유혹이 생길 수 있다. 그건 지양해야된다고 배웠다.
그러니 일단 언어와 문법은 문제를 마주하면서 검색을 통해 배워나가자.
그리고 알고리즘은 나의 머릿속에서 도출해낼 수 있다는 스스로에 대한 믿음을 가지자. (책을 읽고 공부는 하면서)
'Today I Errored 🔥 (문제해결력)' 카테고리의 다른 글
| [플러터] No Firebase App '[DEFAULT]' 에러 (0) | 2023.04.11 |
|---|---|
| 파이어베이스 애널리틱스 api를 붙이는 과정에서 생기는 버전 에러 (0) | 2023.04.10 |
| [백준] DFS문제를 풀면서 얻은 교훈 (0) | 2023.03.08 |
| [백준] '틀렸습니다'를 마주했을 때의 태도 (0) | 2023.03.06 |
| 입력받기 (2) | 2023.03.06 |