개발새발문제

백준 11723 집합(set, remove, discard, .copy)

birdsfoot 2024. 12. 16.

문제설명

- 비어있는 공집합 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를 공집합으로 바꾼다.

입력값

1. 수행해야 하는 연산의 수 M
2. M개줄에 걸쳐 수행해야하는 연산이 한 줄에 하나씩 주어진다

출력값

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

 

 

 

1차 시도

- remove는 set이 비어있을 때 error가 발생하므로 주의

# 메모리 초과

import sys
input = sys.stdin.readline

M = int(input())
S = set()

# all_S = [x for x in range(1,21)]
# 속도를 위해 set으로 만듦

all_S = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}


for _ in range(M) :
    request = input().split()

    if request[0] == 'all' :
        S = all_S

    elif request[0] == 'empty' :
        S = set()
    
    # 이 경우엔 무조건 request[1]이 존재함
    else :
        if request[0] == 'add' :
            S.add(int(request[1]))

        elif request[0] == 'remove' :
            if int(request[1]) in S :
                S.remove(int(request[1]))
                # remove는 값이 없으면 error를 발생시키므로 주의
                
        elif request[0] == 'check' :
            if int(request[1]) in S :
                print(1)
            else :
                print(0)

        elif request[0] == 'toggle' :
            if int(request[1]) in S :
                S.remove(int(request[1]))
            else :
                S.add(int(request[1]))

 

 

2차 시도

- remove를 사용하면 set이 비어있는지 한번 더 확인하는 과정이 필요함

- set이 비어있어도 오류가 발생하지 않는 discard로 수정

- 그런데도 오답!

- `S=all_S`를 할 때 발생하는 문제 때문이었음

- 수정하니 정답

# 값이 없으면 오류를 만드는 remove 대신 값이 없어도 오류를 발생시키지 않는 discard로 수정
# 32412KB, 3080ms

import sys
input = sys.stdin.readline

M = int(input())
S = set()

# all_S = [x for x in range(1,21)]
# 속도를 위해 set으로 만듦

all_S = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}


for _ in range(M) :
    request = input().split()

    if request[0] == 'all' :
        S = all_S.copy()
        # S = all_S  # 이렇게 하면 S가 수정될 때 all_S도 같이 수정될 수 있음

    elif request[0] == 'empty' :
        S = set()
    
    # 이 경우엔 무조건 request[1]이 존재함
    else :
        if request[0] == 'add' :
            S.add(int(request[1]))

        elif request[0] == 'remove' :
            S.discard(int(request[1]))
            # 값이 없어도 에러를 발생시키지 않음

        elif request[0] == 'check' :
            if int(request[1]) in S :
                print(1)
            else :
                print(0)

        elif request[0] == 'toggle' :
            if int(request[1]) in S :
                S.remove(int(request[1]))
            else :
                S.add(int(request[1]))

 

 

.copy

all_S = {1, 2, 3}
S = all_S
# 동일한 객체를 가리키게 됨

S.add(4)
print(S)      # 출력: {1, 2, 3, 4}
print(all_S)  # 출력: {1, 2, 3, 4} (all_S도 변경됨!)

- 단순히 `S = all_S`를 하면 동일한 객체를 참조하게 되서 S를 수정할 때 all_S도 함께 수정됨

 

파이썬 튜터

 

all_S = {1, 2, 3}
S = all_S.copy()

S.add(4)
print(S)      # 출력: {1, 2, 3, 4}
print(all_S)  # 출력: {1, 2, 3} (all_S는 변경되지 않음!)

- .copy()를 하면 복사본을 새롭게 만들기 때문에 원본이 수정되지 않음

 

댓글