CodingTest/BeakJoon

[10828] 스택

the.Dev.Cat 2026. 3. 24. 01:45

 

백준 Silver IV | 10828 | Python | 문제 링크

문제 설명

정수를 저장하는 스택을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 다섯 가지이다.

  • push X: 정수 X를 스택에 넣는 연산이다.
  • pop: 스택에서 가장 위에 있는 정수를 빼고, 그 수를 출력한다. 만약 스택에 들어있는 수가 없는 경우에는 -1을 출력한다.
  • size: 스택에 들어있는 정수의 개수를 출력한다.
  • empty: 스택이 비어있으면 1, 아니면 0을 출력한다.
  • top: 스택의 가장 위에 있는 정수를 출력한다. 만약 스택에 들어있는 수가 없는 경우에는 -1을 출력한다.

입력

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다.

출력

출력이 있는 명령에 대해서 출력을 한다.

입출력 예

입력 출력
14
push 1
push 2
top
size
empty
pop
pop
pop
push 10
top
empty
pop
size
empty
2
2
0
2
1
-1
10
0
10
1
0
 

나의 풀이

풀이 1 - 첫 번째 제출과 버그 수정

import sys
input = sys.stdin.readline
n = input()
stack = []
for line in sys.stdin:
    command = []
    command = line.split()
    if command[0] == "push":
        stack.append(command[1])
    elif command[0] == "pop":
        stack.pop() if stack else print(-1)
    elif command[0] == "size":
        print(len(stack))
    elif command[0] == "empty":
        print(0 if stack else 1)
    elif command[0] == "top":
        print(stack[-1] if stack else -1)

제출하고 채점 결과를 기다리면서 이미 맞은 것처럼 생각하고 있었다. 스택 비어있을 때 -1 출력하는 것도 처리했고, 명령어 파싱도 됐으니까. 그런데 틀렸다가 떴다.

처음엔 이해가 안 됐다. 어디서 틀렸는지 바로 보이지 않았다. 코드를 다시 한 줄씩 읽었다.

버그 1 — pop이 아무것도 출력하지 않았다

stack.pop() if stack else print(-1)

이 줄이 문제였다. 스택이 비어있으면 -1을 출력하는데, 값이 있으면 꺼내기만 하고 출력을 하지 않는다. pop은 꺼낸 값을 반환하는데, 반환값을 print로 감싸지 않았다.

고치는 건 간단했다. print()로 전체를 감싸면 된다.

print(stack.pop() if stack else -1)

이 두 줄이 얼마나 달라 보이지 않는지가 당황스러웠다. stack.pop() if stack else print(-1)print(stack.pop() if stack else -1). 읽으면서 같은 동작을 한다고 착각했던 것 같다.

pop 버그를 찾고 나서 코드를 다시 처음부터 읽었다. 틀렸다는 게 확인된 이상, 다른 곳에도 비슷한 실수가 있을 것 같았다.

버그 2 — n을 int로 변환하지 않았다

n = input()

sys.stdin.readline으로 읽으면 문자열 "10\n" 같은 형태가 들어온다. 이걸 int()로 변환하지 않으면 n은 숫자가 아니라 문자열이다. 이 문제에서는 n을 반복문이나 산술 연산에 사용하지 않아서 실제 오답으로 이어지지는 않았다. 하지만 n을 range(n)이나 비교 연산에 쓰는 순간 TypeError가 발생한다.

버그 3 — command = []가 아무 의미가 없었다

command = []
command = line.split()

빈 리스트로 초기화하고 바로 다음 줄에서 line.split() 결과로 덮어씌운다. 초기화가 의미 없는 코드이다. 파이썬에서는 그냥 바로 대입하면 된다.

버그 4 — push할 때 정수로 변환하지 않았다

stack.append(command[1])

command[1]은 문자열 "5" 같은 형태이다. 이 문제에서는 스택에 넣은 값을 그대로 출력만 하기 때문에 문자열이어도 정답으로 처리된다. 하지만 스택에 넣은 값을 더하거나 비교하는 문제에서는 바로 오답이 난다.

빈 스택 예외처리도 반드시 해야 한다. pop()top에서 스택이 비어 있을 때 예외처리를 빠뜨리면 IndexError가 나서 런타임 에러로 처리된다.

stack.pop() if stack else -1
stack[-1] if stack else -1

처음에는 이것만 신경 써도 충분하다고 생각했는데, 알고 보니 출력을 빠뜨리는 더 기본적인 실수를 하고 있었다.

풀이 2 - 최종 제출 코드

import sys
input = sys.stdin.readline

n = int(input())
stack = []

for line in sys.stdin:
    command = line.split()

    if command[0] == "push":
        stack.append(int(command[1]))
    elif command[0] == "pop":
        print(stack.pop() if stack else -1)
    elif command[0] == "size":
        print(len(stack))
    elif command[0] == "empty":
        print(0 if stack else 1)
    elif command[0] == "top":
        print(stack[-1] if stack else -1)

풀이 3 - 결과를 모아서 한 번에 출력

import sys
input = sys.stdin.readline

n = int(input())
stack = []
result = []

for _ in range(n):
    command = input().split()

    if command[0] == "push":
        stack.append(int(command[1]))
    elif command[0] == "pop":
        result.append(stack.pop() if stack else -1)
    elif command[0] == "size":
        result.append(len(stack))
    elif command[0] == "empty":
        result.append(0 if stack else 1)
    elif command[0] == "top":
        result.append(stack[-1] if stack else -1)

print('\n'.join(map(str, result)))

풀이 2와 차이가 두 가지 있다.

하나는 for line in sys.stdin 대신 for _ in range(n)을 쓴다. 읽어들인 n을 실제로 활용하는 방식이다.

다른 하나는 출력을 매번 print()로 하는 대신 result 리스트에 모아두고, 마지막에 '\n'.join(map(str, result))로 한 번에 출력한다. print()를 반복 호출하면 그만큼 I/O가 발생하는데, 한 번에 출력하면 그 횟수를 줄일 수 있다. 입력 데이터가 많은 문제에서 차이가 난다.