2 분 소요

11723번: 집합

문제

비어있는 공집합 S가 주어졌을 때, 아래 연산을 수행하는 프로그램을 작성하시오.

  • add x: S에 x를 추가한다. (1 ≤ x ≤ 20) S에 x가 이미 있는 경우에는 연산을 무시한다.
  • remove x: S에서 x를 제거한다. (1 ≤ x ≤ 20) S에 x가 없는 경우에는 연산을 무시한다.
  • check x: S에 x가 있으면 1을, 없으면 0을 출력한다. (1 ≤ x ≤ 20)
  • toggle x: S에 x가 있으면 x를 제거하고, 없으면 x를 추가한다. (1 ≤ x ≤ 20)
  • all: S를 {1, 2, …, 20} 으로 바꾼다.
  • empty: S를 공집합으로 바꾼다.

입력 조건

첫째 줄에 수행해야 하는 연산의 수 M (1 ≤ M ≤ 3,000,000)이 주어진다.

둘째 줄부터 M개의 줄에 수행해야 하는 연산이 한 줄에 하나씩 주어진다.

출력 조건

check 연산이 주어질때마다, 결과를 출력한다.


첫 번째 시도 .

 m = int(input())
 S = set([])
 
 for _ in range(m):
     cmd = input().split()
     if len(cmd) == 2:
         word = cmd[0]
         num = int(cmd[1])
     else:
         word = cmd[0]
     
     if word == 'add':
         S.add(num)
     
     if word == 'remove':
         if num in S:
             S.remove(num)
     
     if word == 'check':
         if num in S:
             print(1)
         else:
             print(0)
     
     if word == 'toggle':
         if num in S:
             S.remove(num)
         else:
             S.add(num)
     
     if word == 'all':
         S = set([i for i in range(1,21)])
     
     if word == 'empty':
         S = set([])
         

»output

 런타임에러 (NameError) + 시간초과 + 메모리초과

image-20220218152048988

🌝 Thinking

제일 처음 시간 초과가 나서 코드의 효율성을 약간 상승시킨 후 다시 제출 하였는데 이번에는 메모리초과가 났다.

엥,, 메모리 초과는 정말 예상치 못한 변수라고 생각했다..

혹시 python3보다 속도가 빠른 pypy3를 이용하여서 그런가? 하는 생각이 들어

python으로 제출하였더니 이번에는 런타임에러(NameError)가 났다… 그래도 메모리초과 문제는 해결 된것이니깐…

(pypy3가 속도가 빠른대신 메모리를 더 소모한다는 글을 본적이 있었다. 속도와 메모리는 반비례하는 것일까 ?)

그럼 대체 NameError는 왜 났을 까?



두 번째 시도 .

import sys
input = sys.stdin.readline
m = int(input())
S = set([])

for _ in range(m):
    cmd = input().split()
    if len(cmd) == 2:
        word = cmd[0]
        num = int(cmd[1])
        
        if word == 'add':
            S.add(num)
    
        if word == 'remove':
            if num in S:
                S.remove(num)
    
        if word == 'check':
            if num in S:
                print(1)
            else:
                print(0)
    
        if word == 'toggle':
            if num in S:
                S.remove(num)
            else:
                S.add(num)
        
    else:
        if cmd[0] == 'all':
            S = set([i for i in range(1,21)])
        else:
            S = set([])
   

»intput

26
add 1
add 2
check 1
check 2
check 3
remove 2
check 1
check 2
toggle 3
check 1
check 2
check 3
check 4
all
check 10
check 20
toggle 10
remove 20
check 10
check 20
empty
check 1
toggle 1
check 1
toggle 1
check 1

»output

1
1
0
1
0
1
0
1
0
1
1
0
0
0
1
0

success

image-20220218152740850

🌝 Thinking

NameError 가 나는 이유는 선언되지 않은 변수를 사용하는 경우때문에 자주 일어난다고 한다.

그래서 특정 조건에서만 선언되는 변수가 있나 살펴보니 num이라는 변수가 있었다.

num 변수는 cmd문자가 2개 일때만 생성되는 변수였기 때문에 all같은 명령이 주어졌을 때

num은 선언이 되어지지 않은 상태로 num이 호출을 받는다.

그래서 런타임 에러가 났던 것이었다.




💡 깨달은 점.

  1. 조건부로 선언되어지는 변수가 있을 때는 런타임에러(NameError)가 발생하지 않도록 유의해야겠다.
  2. pypy3는 python3보다 속도 측면에서는 효율적이나 메모리는… 그러하지 않는 듯 하다.

댓글남기기