본문 바로가기
Tech/Coding

파이썬🐨더욱 더 로우레벨한 입출력

by redcubes 2024. 7. 31.
import os
arr = list(map(int, os.read(0, os.fstat(0).st_size).split()))
is_hacker = any((((i // 2) + 1) * 100) < arr[i] for i in range(len(arr)))
open(1, "w").write(["draw", "none", "hacker"][(sum(arr) < 100) + (is_hacker << 1)])

 

제시된 코드는 os.reados.fstat를 사용하여 표준 입력으로부터 데이터를 읽고 처리하는 방식으로 작성된 코드이다. 이 코드의 동작 방식과 sys.stdin, open(0), input()과의 차이점을 자세히 설명하겠다.

코드 분석

import os

# 표준 입력으로부터 데이터를 읽어온다
arr = list(map(int, os.read(0, os.fstat(0).st_size).split()))

# 조건에 따라 'hacker'인지 아닌지 판별
is_hacker = any((((i // 2) + 1) * 100) < arr[i] for i in range(len(arr)))

# 결과를 출력한다
open(1, "w").write(["draw", "none", "hacker"][(sum(arr) < 100) + (is_hacker << 1)])

각 코드의 역할

  1. os.read(0, os.fstat(0).st_size):
    • os.read(fd, n) 함수는 파일 디스크립터 fd에서 최대 n 바이트를 읽어온다.
    • os.fstat(fd).st_size는 파일 디스크립터 fd의 크기를 반환한다. 여기서 0은 표준 입력을 의미하며, os.read(0, os.fstat(0).st_size)는 표준 입력의 전체 내용을 읽어온다.
  2. arr = list(map(int, os.read(0, os.fstat(0).st_size).split())):
    • os.read(0, os.fstat(0).st_size)로 읽어온 데이터를 split()을 통해 공백 기준으로 나누고, 각 요소를 정수로 변환하여 리스트 arr에 저장한다.
  3. is_hacker = any((((i // 2) + 1) * 100) < arr[i] for i in range(len(arr))):
    • any() 함수는 리스트 내의 조건이 하나라도 True인 경우 True를 반환한다.
    • 조건식 ((((i // 2) + 1) * 100) < arr[i])는 각 요소의 인덱스를 기반으로 조건을 평가한다. i // 2는 인덱스를 두 개씩 나누고, 거기에 1을 더한 후 100을 곱한다. 이 값이 arr[i]보다 작은 경우가 있는지 확인한다.
  4. open(1, "w").write(["draw", "none", "hacker"][(sum(arr) < 100) + (is_hacker << 1)]):
    • sum(arr) < 100True면 1, False면 0으로 평가된다.
    • is_hackerTrue이면 1, False면 0이며, << 1은 비트 시프트 연산을 통해 1을 곱한 것과 같다.
    • 결과적으로 ["draw", "none", "hacker"] 리스트의 인덱스를 계산하여 적절한 결과를 표준 출력에 쓴다.

표준 입력과 출력 방법

  1. input():
    • input()은 표준 입력으로부터 한 줄을 읽어오는 함수이다. 사용자가 입력을 완료하고 Enter를 누를 때까지 기다린다.
    • 이 함수는 기본적으로 문자열로 반환되며, 작은 입력에 적합하고 간편하게 사용할 수 있다.
  2. sys.stdin:
    • sys.stdin은 표준 입력을 나타내는 파일 객체이다. sys.stdin.read()는 모든 입력을 문자열로 읽어오고, sys.stdin.readline()은 한 줄씩 읽어온다.
    • 이 방식은 대규모 데이터를 처리할 때 적합하다.
  3. os.reados.fstat:
    • os.read(0, n)은 파일 디스크립터 0에서 최대 n 바이트를 읽어오며, os.fstat(0).st_size를 사용하여 표준 입력의 크기를 얻을 수 있다.
    • 이 방식은 빠른 입출력에 유용하며, 특히 바이너리 데이터 처리에 적합하다.
  4. open(0):
    • open(0, "r")로 표준 입력을 파일로 취급하여 데이터를 읽을 수 있다. 이 방식은 고성능 입출력에 적합하다.

비교 및 요약

  • 간편성: input()이 가장 간단하며 사용자와 상호작용하는 일반적인 입력에 적합하다.
  • 유연성: sys.stdin은 다량의 텍스트 데이터를 처리하는 데 적합하다.
  • 고성능: os.readopen(0)은 대량의 데이터 입력 또는 바이너리 데이터를 처리할 때 유용하다. 특히 os.read는 버퍼를 사용하지 않아 빠르게 데이터를 읽을 수 있다.

이러한 방법들은 각각의 사용 목적에 따라 선택할 수 있으며, 데이터 크기와 성능 요구 사항에 따라 적절한 방식을 선택하는 것이 중요하다.

마지막 줄의 출력도 

os.write(1,["draw", "none", "hacker"][(sum(arr) < 100) + (is_hacker << 1)].encode())

처럼 쓸 수 있지만 한 줄 출력에서는 오히려 느려졌다.

 

 

https://gumgood.github.io/python-fastio

 

Python FastIO - 프로그래밍 대회를 위한 파이썬 빠른 입출력 - Gumgood

프로그래밍 대회나 기업 코딩 테스트에서는 제한 시간이 있기 때문에 최대한 빠르게 입출력을 처리하는 것이 중요하다. 특히, C언어에 비해 굉장히 느린 Python은 입출력 자체만으로 시간 초과가

gumgood.github.io

https://m.blog.naver.com/yurhyur1/50122605420

 

파일 입출력, 디스크립터

파일 입출력과 디스크립터라는 것에 대해서 알아 볼텐데, 이것에 대해서 이야기하는 이유는 파일 입출력과 ...

blog.naver.com

https://redcubes.tistory.com/128

 

C 언어 고급편]🚀18 파일 입출력

목차 파일 개방과 입출력 파일 개방과 폐쇄 #include int main(void) { FILE *fp; fp = fopen("a.txt","r"); if (fp == NULL) { printf("파일이 열리지 않았습니다.\n"); return 1; } printf("파일이 열렸습니다.\n"); fclose(fp); retur

redcubes.tistory.com