[알고리즘] 집합

sith-call.dev·2024년 12월 22일
0

알고리즘

목록 보기
47/47

문제

link

나의 코드

import sys
input = sys.stdin.readline
m = int(input())
myset = set()
for _ in range(m):
    parts = input().split()
    cmd = parts[0]
    if cmd == "all":
        myset = set(range(1,21))
        continue
    elif cmd == "empty":
        myset = set()
        continue
    value = int(parts[1])
    if cmd == "add":
        myset.add(value)
    elif cmd == "remove":
        myset.discard(value)
    elif cmd == "check":
        print(1 if value in myset else 0)
    elif cmd == "toggle":
        if value in myset:
            myset.remove(value)
        else:
            myset.add(value)

처음에는 시간 초과가 나서, 도저히 이해할 수가 없었다.
알고리즘 자체에는 문제가 없었기 때문이다. 그래서 GPT에게 도움을 요청한 결과 input 함수에서 시간이 느려질 수 있다는 것을 알았다. 그래서 다음과 같은 두 줄을 추가하고 나서 채점이 통과 됐다.

import sys
input = sys.stdin.readline

고찰

  1. python에서 input 대신에 sys.stdin.readline 을 쓰면 입력 속도가 더 빨라진다. 특히 입력값이 대규모일 때 필요하다.
  2. Python3보다 PyPy3가 더 빠르다.

정리

input() 대신에 sys.stdin.readline 을 쓰면 입력 속도가 더 빨라진다.

input() 함수는 내부적으로 여러 가지 과정을 거치며(예: prompt 출력, EOF 예외 처리, 문자열 변환 등), 한 줄 입력을 받을 때마다 이러한 오버헤드가 누적됩니다. 반면, sys.stdin.readline() 은 표준 입력 버퍼에서 바로 데이터를 읽어 오기 때문에 이러한 오버헤드가 훨씬 적습니다. 특히 반복적으로 많은 줄을 입력받아야 하는 상황(수천~수만 줄 이상)에서, 이 차이가 누적되어 속도 차이가 크게 납니다. 이러한 이유 때문에, 코딩 테스트나 알고리즘 문제 풀이 등에서 대규모 데이터를 입력받을 때 sys.stdin.readline 사용을 권장하는 경우가 많습니다.

  • 중요 포인트는 표준 입력 버퍼를 사용한다는 점!
  • (IMO) 왜냐하면, 입력하는 쪽과 출력하는 쪽이 서로 속도를 싱크 맞출 필요가 없기 때문이다. 입력하는 쪽은 자신의 속도대로 다 입력하고 입력을 종료하면 되고, 출력하는 쪽도 입력하는 쪽과 상관 없이 버퍼에서만 데이터를 읽어오기 때문에, 둘 중 최저 속도로 전체 프로세스 처리 속도가 낮아지지 않아도 된다.

Python3보다 PyPy3가 더 빠르다.

PyPy는 Just-In-Time (JIT) 컴파일러를 사용합니다. CPython(보통 ‘Python3’라고 불리는 표준 구현)은 인터프리터 방식으로, 한 줄씩 코드를 실행합니다. 반면 PyPy는 프로그램 실행 중 ‘반복되는 코드’를 찾아, 그 부분을 기계어로 컴파일해둔 뒤 반복 시에 해당 기계어 코드를 바로 실행합니다. 이 과정에서 오버헤드가 크게 줄어들어, 반복문이 많은 알고리즘 문제나 CPU 연산이 많은 작업에서 속도가 눈에 띄게 빨라지는 경우가 많습니다. 다만, PyPy의 초기 구동 시간이나, 특정 라이브러리 호환성 문제, 또는 NumPy 같은 C 확장 기반 라이브러리의 일부 기능에서 PyPy가 최적화가 덜 된 경우도 있어, 모든 상황에서 무조건 빠른 것은 아닙니다. 일반적으로 파이썬 표준 라이브러리 위주의 알고리즘 문제에서는 PyPy가 유리한 경우가 많다고 알려져 있습니다.

  • pycache와 같이 바이트코드를 생성한 뒤에, 이를 재사용한다는 점에서 빠른다.
  • 그래서 loop가 많은 알고리즘이나, CPU 바운드가 높은 워크로드에서 이점이 있다.

항상 sys.stdin.readline 을 쓰면 좋지 않은가?

대규모 입력값이 있을 땐 그렇다. 하지만, 사용자가 CLI 환경에서 인터렉션이 필요할 땐, 적합하지 않음.

profile
lim (time → ∞) Life(time) = LOVE

0개의 댓글

관련 채용 정보