코딩테스트 - 빈번한 사용

김기훈·2026년 3월 2일

BaekJoon

목록 보기
5/12

팩토리얼

import sys

def factorial(n):
    ans = 1
    for i in range(2, n + 1):
        ans *= i
    return ans

반올림(decimal)

from decimal import Decimal, ROUND_HALF_UP

def traditional_round(number):
    # 숫자를 Decimal 객체로 변환 후, ROUND_HALF_UP 방식으로 정수화
    return int(Decimal(str(number)).quantize(Decimal('1'), rounding=ROUND_HALF_UP))

print(traditional_round(2.5))  # 결과: 3
print(traditional_round(3.5))  # 결과: 4

최빈값

from collections import Counter

def get_mode_with_counter(arr):
    # 초기 상태: arr = [2, 1, 3, 2, 3, -1]

    # 1. 입력 배열을 오름차순으로 미리 정렬합니다.
    arr.sort() 
    # 결과 : arr = [-1, 1, 2, 2, 3, 3]
    
    # 2. Counter를 사용해 빈도수를 계산합니다.
    counter = Counter(arr)
    # 결과 : counter = Counter({-1: 1, 1: 1, 2: 2, 3: 2})
    
    # 3. most_common()은 빈도수 내림차순으로 정렬된 리스트를 반환합니다.
    modes = counter.most_common()
    # 결과 : modes = [(2, 2), (3, 2), (-1, 1), (1, 1)]
    
    # 4. 최빈값이 2개 이상이고, 1위와 2위의 빈도수가 같다면 두 번째로 작은 값 반환
    # modes[0][1] 은 1위(숫자 2)의 빈도수 : 2
    # modes[1][1] 은 2위(숫자 3)의 빈도수 : 2
    if len(modes) > 1 and modes[0][1] == modes[1][1]:
        
        # 두 번째로 작은 값인 2위의 숫자(인덱스 1의 첫 번째 원소)를 반환합니다.
        return modes[1][0] 
    else:
        # 최빈값이 압도적으로 하나뿐이라면 1위의 숫자를 반환합니다.
        return modes[0][0]

# 실행 확인
# print(get_mode_with_counter([2, 1, 3, 2, 3, -1])) # 출력: 3

입력

  • 아래는 둘 다 빠른 입력을 위해 사용되지만
    • 데이터를 읽어오는 방식과 범위에서 명확한 차이가 존재
    • 두 가지의 특징과 예시를 명확하게 비교해보기

sys.stdin.readline()

  • 한 줄씩 순차적으로 읽기

    • 이 함수는 호출될 때마다 입력 스트림에서 딱 한 줄만 읽어옴
  • 특징
    • 엔터(개행 문자, \n)를 만날 때까지의 문자열을 읽어오며, 결과값에 \n이 포함됨
  • 사용하기 좋은 상황
    • 각 줄의 데이터가 독립적인 의미를 가지거나, 줄 단위로 순차적인 처리가 필요할 때 주로 사용
  • .split()을 붙였을 때와 안 붙였을 때

# 입력
10 20 30

# data = sys.stdin.readline()
"10 20 30\n" (끝에 엔터값이 붙은 하나의 문자열)

# data = sys.stdin.readline().split()
['10', '20', '30'] (문자열들이 담긴 리스트)

# data = list(map(int, sys.stdin.readline().split()))
[10, 20, 30] (정수들이 담긴 리스트)
  • 예시

# 입력
3
10 20
30 40

# 출력 
[[10, 20], [30, 40]] (정수 리스트를 원소로 가지는 2차원 리스트)

# 리스트 컴프리헨션 사용
import sys

# 1. 첫 번째 줄 입력
n = int(sys.stdin.readline())

# 2. 리스트 컴프리헨션을 사용하여 2차원 리스트를 한 번에 생성합니다.
data = [list(map(int, sys.stdin.readline().split())) for _ in range(n)]

print(data) # 출력: [[10, 20], [30, 40]]

# sys.stdin.read().split() 활용
import sys

# EOF(End Of File)까지 한 번에 모두 읽어온 뒤 공백/줄바꿈 기준으로 분리합니다.
input_data = sys.stdin.read().split()
# input_data는 현재 ['3', '10', '20', '30', '40'] 형태의 문자열 리스트입니다.

if input_data:
    n = int(input_data[0]) # 첫 번째 값 '3'
    
    data = []
    # 인덱스 1부터 끝까지, 2개씩 짝지어서 2차원 리스트로 만듭니다.
    # (예시의 줄당 원소 개수가 2개('10 20')로 고정되어 있을 때 유용합니다)
    for i in range(1, len(input_data), 2):
        data.append([int(input_data[i]), int(input_data[i+1])])

print(data) # 출력: [[10, 20], [30, 40]]

sys.stdin.read()

  • 전체를 한 번에 통째로 읽기

    • 이 함수는 파일의 끝(EOF)에 도달할 때까지
    • 모든 입력 데이터를 한 번에 읽어와서 하나의 거대한 문자열로 반환
  • 특징
    • I/O(입출력) 호출을 단 한 번만 하므로, 파이썬에서 가장 빠른 입력 방법임
  • 사용하기 좋은 상황
    • 줄바꿈이나 공백에 큰 의미를 두지 않고
    • 전체 데이터를 한꺼번에 리스트 등으로 변환해서 처리하고 싶을 때 매우 강력
  • .split()을 붙였을 때와 안 붙였을 때

# 입력
3
10 20
30 40

# .split()을 안 썼을 때: sys.stdin.read()
"3\n10 20\n30 40\n" (타입: 문자열)

# .split()을 썼을 때: sys.stdin.read().split()
['3', '10', '20', '30', '40'] (타입: 리스트)

비교

  • 입력은 같지만, 내가 코드를 짜기 편한 형태로 데이터를 잘라(파싱해) 두는 방식이 다르다"

  • 예시

# 입력

3
10 20
30 40

# sys.stdin.read().split()으로 받았을 때 저장되는 형태

['3', '10', '20', '30', '40'] (1차원 리스트 하나에 모두 저장)

# sys.stdin.readline()을 3번 호출해서 받았을 때 저장되는 형태

첫 번째 변수 = '3\n'
두 번째 변수 = '10 20\n'
세 번째 변수 = '30 40\n'

비교 2

  • sys.stdin.read().split() / sys.stdin.readline().split()
# 입력
3 
10
20
30
40 
50

# readline().split()
딱 첫 줄인 ['3']만 가져옴, 다 가져오려면 for문을 돌리면서 여러 번 호출해야 함 

# read().split()
줄바꿈을 다 무시하고 ['3', '10', '20', '30', '40', '50'] 이라는 하나의 리스트로 깔끔하게 다 가져옴
profile
안녕하세요.

0개의 댓글