요즘 PS 스터디에 참여하고 있다. 함께 선택한 문제를 주중에 하루 1문제씩 풀고, 주말 특정 시간에 zoom에서 모여 코드 리뷰를 하는 방식이다. 코딩 테스트라는 저 너머의 목적이 있지만, 꾸준히 조금씩이나마 경진형 프로그래밍을 통해 심오하게 짱구를 굴려서 로직을 설계하고 코드로 구현하는 연습 내지는 습관을 들이려는 커다란 목적도 있다. 또한 정답 처리 받고 넘어가는 게 아니라, 해당 문제와 제출 코드를 둘러싼 온갖 '왜?'를 정리해 보고 이해하기 쉽게 표현해서 학습 효과를 높이려는 목적도 있다. 아직까지는 그 목적이 다 달성되고 있어서 참 좋다. 효율적인 스킬이나 바람직한 코드 스타일에 대한 의견을 공유하면서 배워가는 것 자체가 많기도 하다.
https://www.acmicpc.net/problem/18222
18222번: 투에-모스 문자열
0과 1로 이루어진 길이가 무한한 문자열 X가 있다. 이 문자열은 다음과 같은 과정으로 만들어진다. X는 맨 처음에 "0"으로 시작한다. X에서 0을 1로, 1을 0으로 뒤바꾼 문자열 X'을 만든다. X의 뒤에
www.acmicpc.net
오늘은 이 문제가 내 몫이었다. 분할 정복의 냄새가 물씬 풍기는 문자열 생성의 로직. 그 점을 착안해 시간복잡도 O(logN)으로 푸는 풀이를 발표했다. 오늘은 지금까지의 스터디 활동 중 가장 인상적인 날이다. 달리 말하면 가장 기분이 들떴던 날이다. "와~" 하는 다른 사람의 감탄 어린 표정을 zoom이라는 공간에서 처음 본 날이기도 하다. 코딩과 관련해서 몸 둘 바를 모를 정도로 칭찬을 받아본 첫 경험이기도 하다. PS를 누군가와 같이 진행한 첫 경험은 '버스 타기'였다. 작년 5월, 학교 수업 시간에 페어 프로그래밍을 할 때 내 짝은 백준 플래티넘 티어의 실력자였고, 아직 실버 티어였던 나는 표준입력을 받는 코드만 달랑 몇 줄 완성해놓고, 그 사람이 DP를 이용해 코딩하는 것을 보며 "와~"로 일관했었다. 그런 기억이 떠올라서 그런지, 오늘 스터디원들의 반응이 더욱 달가웠다.
확실히 오늘의 나는 다른 날과 달랐다. 보통 때 같았으면 '저 사람들에게 내 메시지가 잘 전달되고 있으려나?'하는 염려가 오히려 메시지 전달력을 약화시켰다면, 오늘은 나름대로 시각화도 하고, 내가 해당 알고리즘과 로직을 잘 알고 있다는 확신도 있어서, 꽤 매끄럽게 발표할 수 있었다. 살면서 거의 경험해 본 적 없는 '발표할 때의 침착함'은 충분하다 싶은 준비와 충분함에 대한 확신에서 나오는 것 같다.
오늘 처음으로 코드포스 온라인 대회에 참가해봤다. 영어로 된 지문이 장벽까지는 아니었지만, 정답을 향해 나아가는 길에 꽤 긴 시간을 허우적대게 만드는 늪지대였다. 2시간 동안 7문제 중 첫 2문제를 풀고, 3번째 문제의 '시간 초과'에서 5번 연속으로 막혔다.
아래는 마지막 제출 코드다. 내가 구현한 로직 안에서 최적화를 이뤄내기 위해, 자료구조를 바꿔보고 하다가 대회 종료 시간이 임박해서, 다시 훑어보지도 못하고 후다닥 제출했다. 대회가 끝나고 생각해보니, 최악의 경우 시간복잡도가 O(N^2)이었다. 어떻게 접근해야 개선할 수 있는지는 아직도 잘 모르겠다.
import sys
from collections import deque
from typing import List
input = sys.stdin.readline
MAX_N = 2 * 100_000
def solution(a_list: List[int]) -> List[str]:
b_list = []
mex_limit = max(a_list) + 1
a_list.reverse()
while len(a_list):
current_mex = 0
contained_set = set()
best_k, best_mex = 0, -1
for k in range(1, len(a_list) + 1):
contained_set.add(a_list[len(a_list) - k])
while current_mex in contained_set:
current_mex += 1
if current_mex > best_mex:
best_mex = current_mex
best_k = k
if best_mex == mex_limit:
break
b_list.append(str(best_mex))
for i in range(best_k):
a_list.pop(-1)
return b_list
if __name__ == '__main__':
t = int(input())
for tc in range(t):
n = int(input())
a_list = list(map(int, input().split()))
sol = solution(a_list)
print(len(sol))
print(' '.join(sol))
시작하기 전에 대회 중에 마실 물을 챙겨놓았는데, 그랬다는 사실마저 잊고 있었다. 전 세계의 사람들과 함께 경쟁하는 대회라 그런지, 백준의 온라인 대회보다 한층 더 긴장감이 있었다. 문제가 한국어로 제공되었다고 해도, 오늘과 같은 결과였을 것 같다. 내게 익숙한 '직관'의 범위를 넓혀야겠다는 생각이 한층 더 깊어진다.
'내가 가는 여정을 담는 그릇' 카테고리의 다른 글
[나의 작은 프로그래밍] TodoTracker (v.1.1.1) (0) | 2022.03.10 |
---|---|
백준 플래티넘 달성 (0) | 2022.02.09 |
PS 풀 때는 마음대로지만, 해설할 때는 아니란다 (0) | 2022.01.20 |
자바의 정석 (0) | 2022.01.03 |
첫 코드 리뷰 작성 (0) | 2021.12.29 |