본문 바로가기

취업과 기본기 튼튼/코딩 테스트 노트

파이썬으로 문제 풀 때 주의해야할 점들

요새 코딩 테스트 문제 푸는 것을 파이썬 스타일로 바꾸려 하고있다.
나는 원래 문제풀 때 c++ 유저였는데 (대학생활 내내 c++ 이었다.), 뒤늦게 나마 바꾸려 하니, 사실 적응이 잘 안가는 것도 사실이다.
그렇다보니, 파이썬 코드를 짜더라도, 굉장히 c 스러운 모습이 보이는데, 이 역시 바꾸려고 하나씩 공부 중이기도 하다.

각설하고, 백준 저지 에서 c 로 풀면 정답으로 간주되는 것이, 파이썬으로 풀면 정답으로 간주되지 않는 경우가 간혹 있다.
이 때, 어떻게 해야할지 발견한 몇 가지를 여기에 적어본다.

1. input() 말고 sys.stdin.readline() 를 사용하자.

결론만 말하자면, 입출력 속도가 다음과 같다.

sys.stdin.readline() > raw_input() > input()

뭐 어느정도로 더 빠르고 느리냐는, 코딩 테스트 문제푸는 수준에서 다룰만한 내용이 아니므로 넘어가도록 하고, 직관적으로만 느꼈던 것은, input() 으로 코드를 제출할 시, 시간초과가 뜨지만, sys.stdin.readline() 으로 제출할 시 정답이 뜨더라는 것이다. 이와 비슷한 이슈는 이미 이전부터 있었다.

한편, 나는 입출력을 지금까지 이런 방식으로 했다.

a = [int(x) for x in input().split()]  
# a = [1, 2, 3, 4 ,5]

하지만, 이 방법보다 다음 방법이 더 권장된다. (위와 같은 이유로)

import sys  
a = list(map(int, sys.stdin.readline().split()))
# a = [1, 2, 3, 4, 5]

여러 라인 입력받아야 할 경우, 다음 방법이 빠르다고 한다.

import sys  
n = input()  
a = [sys.stdin.readline() for i in range(n)]  
# a = ["1 2 3", "4 5 6"]

2. 재귀함수가 있는 경우, 최대 재귀 깊이를 설정해줘야 한다.

이전에 문제풀다가 말한 적이 있는데, 특히 자주접하는 DFS, BFS 문제의 경우 그렇다.

파이썬의 재귀 허용 깊이의 기본치가 c 보다 약한건지, c 로 짠 DFS, BFS의 경우 문제 없이 돌아가지만, 파이썬으로 돌리면 런타임 오류가 뜨는 경우가 있다. 그래서 다음과 같이 재귀 허용 깊이를 수동으로 늘려주는 코드를, 코드 상단에 적어줘야 한다.

import sys  
sys.setrecursionlimit(10**8) # 10^8 까지 늘림.

3. PyPy vs Python3

이렇게 해도 정답이 아니라고 뜨는 경우가 있는데, 이 때 파이썬3가 아니라 PyPy로 언어를 바꿔 제출하면 된다.

PyPy 가 뭔지 찾아보니, 쉽게말해 파이썬 보다 몇 배 더 빠른 개선된 파이썬이라고 생각하면 된다.

좀 더 자세히 말하면, Python3 는 내부적으로는 C로 짜여져있는데 (이 이유 때문에 Python2 보다 빠르다.), 이를 C가 아니라 Python으로 다시 짠 것이다. 당연히 느릴 것 같은데, 의외로 빠르단다. 자세한 내용은 나무위키 참고.

때문에, 일반적으로 Python3 보다 PyPy로 제출해서 내는게 더 안전한 듯 하다. (빠르다는 의미에서)

한편, PyPy에서는 sys.setrecursionlimit(10**8) 이 안먹는다. 즉 임의로 재귀 호출 깊이를 설정할 수 없다는 것에 주의해야 한다.

파이썬으로 문제푸는 게 편한점도 많지만 아직 어색하고, 이런 자잘한 리스크가 많은 듯 하다.
이후 또 뭔가 발견하면 남겨놔야겠다.