간혹 낮은 난이도의 문제에서 유틸리티 관련 메서드에 대해 물어보는 경우가 있기 때문에, 이러한 메서드도 미리 알아두면 쉬운 문제를 빠르게 푸는 데에 도움이 될 것이다.
from datetime import date, datetime, timedelta
# 오늘의 날짜
print(date.today()) # 2024-08-29
# 오늘의 날짜 + 현재 시간
print(datetime.now()) # 2024-08-29 00:22:00.635581
# 출력 형식 지정
print(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) # 2024-08-29 00:22:00
# 현재 시간으로부터 2시간 30분 30초가 지난 시점
print(datetime.now() + timedelta(hours=2, minutes=30, seconds=30)) # 2024-08-29 02:52:30.635581
※ 관련 문제
>> 백준 10699번
## 정답 코드 ##
from datetime import date
print(date.today())
① 대소문자 확인
S = input().strip() # HeLlO 입력
for s in S:
if s.isupper():
print("U", end=' ')
if s.islower():
print("L", end=' ')
# U L U L U 출력
② 대소문자 변환
S = input().strip() # HeLlO 입력
# <대-소 변환>
print(S.swapcase()) # hElLo 출력
# <소문자 변환>
print(S.lower()) # hello 출력
# <대문자 변환>
print(S.upper()) # HELLO 출력
※ 관련 문제
"q1/w2e*3r^4"와 같이 숫자, 알파벳, 특수문자가 혼재되어 있는 문자열이 주어진다. 주어진 문자열에서 알파벳은 다음 알파벳으로, 숫자는 +1, 특수문자는 그대로 유지하여 결과 문자열을 출력하라. (단, 알파벳이 z인 경우는 a로, 숫자가 9인 경우는 0을 사용한다.)
위 문제를 풀이하려면 전체 문자열을 순회하면서, 현재 문자가 알파벳인지 숫자인지를 파악할 수 있어야 할 것이다. 이 때 사용할 수 있는 메서드에는 isalpha()
, isdigit()
가 있다. 한 가지 주의해야 할 점은 두 메서드 모두 dot operator 형식으로 사용해야 한다는 것이다.
① isalpha()
a = 'q1w2e3r4'
b = '1234'
c = 'qwer'
print(a.isalpha()) # False
print(b.isalpha()) # False
print(c.isalpha()) # True
② isdigit()
a = 'q1w2e3r4'
b = '1234'
c = 'qwer'
print(a.isdigit()) # False
print(b.isdigit()) # True
print(c.isdigit()) # False
③ isalnum()
a = 'q1w2e3r4'
b = 'qwer'
c = '1234'
d = '***'
e = 'q1w2e3r4/'
print(a.isalnum()) # True
print(b.isalnum()) # True
print(c.isalnum()) # True
print(d.isalnum()) # False
print(e.isalnum()) # False
따라서, 위 문제는 아래와 같이 풀이할 수 있을 것이다.
S = 'q1/w2e*3r^4'
result = []
for char in S:
if char.isdigit(): # 숫자인 경우
# 9일 때는 0으로 순환
result.append(str((int(char) + 1) % 10))
elif char.isalpha(): # 알파벳인 경우
# 'z' 또는 'Z'는 'a' 또는 'A'로 순환
if char == 'z':
result.append('a')
elif char == 'Z':
result.append('A')
else:
result.append(chr(ord(char) + 1))
else:
result.append(char) # 다른 문자는 그대로 추가
print(''.join(result))
pow(a, b, c)를 이용하면, pow(a, b) % c보다 더 빠르게 값을 구할 수 있다.
※ 관련 문제
>> 백준 1629번
## 정답 코드 ##
import sys
input = sys.stdin.readline
a, b, c = map(int, input().split())
print(pow(a, b, c))
파이썬의 itertools 모듈을 사용하면, 순열 또는 조합에 대한 Iterator를 얻을 수 있으며, Iterator의 사용법은 아래와 같다.
from itertools import permutations, combinations, combinations_with_replacement
lst = ['A', 'B', 'C']
# 3개의 원소로 구성할 수 있는 순열을 순회 -> 6만큼의 경우의 수 존재
for i in permutations(lst):
print(i)
print()
# 3개의 원소 중 2개를 선택한 조합을 순회 -> 3만큼의 경우의 수 존재
for i in combinations(lst, 2):
print(i)
print()
# 3개의 원소 중 2개를 중복 선택한 조합을 순회 -> 6만큼의 경우의 수 존재
for i in combinations_with_replacement(lst, 2):
print(i)
## 출력 ##
('A', 'B', 'C')
('A', 'C', 'B')
('B', 'A', 'C')
('B', 'C', 'A')
('C', 'A', 'B')
('C', 'B', 'A')
('A', 'B')
('A', 'C')
('B', 'C')
('A', 'A')
('A', 'B')
('A', 'C')
('B', 'B')
('B', 'C')
('C', 'C')
※ 관련 문제
>> 백준 15686번
## 정답 코드 ##
import sys
input = sys.stdin.readline
from itertools import combinations
N, M = map(int, input().split())
graph = [list(map(int, input().split())) for i in range(N)]
house = [] # 집의 좌표
chicken = [] # 치킨집의 좌표
for i in range(N):
for j in range(N):
if graph[i][j] == 1: # 집인 경우
house.append((i, j))
if graph[i][j] == 2: # 치킨집인 경우
chicken.append((i, j))
result = sys.maxsize # 최소 값을 구하기 위해 매우 큰 값으로 초기화
for comb in combinations(chicken, M): # 치킨집 리스트에서 M개를 선택하는 경우의 수를 순회
total_dist = 0 # 모든 집의 치킨 거리의 합
for h in house:
house_chicken_dist = sys.maxsize
for j in range(M): # 각 집과 가장 가까운 치킨집까지의 거리를 구함 (거리는 |r1-r2| + |c1-c2|로 구함)
house_chicken_dist = min(house_chicken_dist, abs(h[0] - comb[j][0]) + abs(h[1] - comb[j][1]))
total_dist += house_chicken_dist
result = min(result, total_dist) # 각 조합마다 구해진 치킨 거리 값중 최소가 되는 값으로 업데이트
print(result)
몫과 나머지를 동시에 구하기 위해 내장 함수인 divmod()
메서드를 활용할 수 있다.
quotient, remainder = divmod(10, 3)
print(quotient) # 3
print(remainder) # 1
S = set()
S.add(1) # 원소 삽입
S.remove(1) # 원소 삭제
S.discard(1) # 해당 원소가 존재하지 않아도 에러가 발생하지 않음
S.clear() # 공집합
참고로, 리스트를 바로 집합에 삽입하는 것은 불가하다. 따라서, 집합에 리스트를 삽입해야 하는 경우, 반드시 먼저 튜플로 변환해야 한다.
S.add(tuple(lst))
집합 연산을 사용하여 if문의 조건식을 작성하는 경우, 아래와 같은 연산자가 사용된다.
&
|
-
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
# 교집합이 공집합이 아니거나, 합집합의 크기가 6보다 크다면
if (A & B) or (len(A | B) > 6):
...
intersection
union
difference
set1 = set1.union(set2) # set1과 set2의 합집합
set1 = set1.intersection(set2) # set1과 set2의 교집합
set1 = set1.difference(set2) # set1과 set2의 차집합
※ 관련 문제
>> 백준 1043번
## 정답 코드 ##
import sys
input = sys.stdin.readline
N, M = map(int, input().split())
know = set(map(int, input().split()[1:]))
parties = []
for i in range(M):
parties.append(set(map(int, input().split()[1:])))
for i in range(M):
for party in parties:
if party & know:
know = know.union(party)
cnt = 0
for party in parties:
if not (party & know):
cnt += 1
print(cnt)
① BFS로 최단 거리를 구하는 문제
※ 관련 문제
>> 백준 13549번
## 정답 코드 ##
import sys
input = sys.stdin.readline
from collections import deque
N, K = map(int, input().split())
visited = [-1] * (100001)
def bfs(V):
deq = deque()
deq.append(V)
visited[V] = 0
while deq:
V = deq.popleft()
if V == K:
print(visited[V])
exit()
if V <= 50000 and visited[2 * V] == -1:
deq.append(2 * V)
visited[2 * V] = visited[V]
if V > 0 and visited[V - 1] == -1:
deq.append(V - 1)
visited[V - 1] = visited[V] + 1
if V < 100000 and visited[V + 1] == -1:
deq.append(V + 1)
visited[V + 1] = visited[V] + 1
bfs(N)
② 두 가지 연산을 이용해서 숫자 A를 B로 변환하는 문제
※ 관련 문제
>> 백준 16953번
## 정답 코드 ##
A, B = map(int, input().split())
def bfs(V, cnt):
deq = deque()
deq.append((V, cnt))
while deq:
V, cnt = deq.popleft()
if V == B:
print(cnt)
exit()
elif V > B:
continue
deq.append((2 * V, cnt + 1))
deq.append((V * 10 + 1, cnt + 1))
print(-1)
bfs(A, 1)
주어진 문자열에서 문자의 개수를 Dictionary에 저장해야 하는 상황은 매우 빈번하다. 이러한 상황에선, 아래와 같이 직접 Dictionary를 정의하여 풀이할 수 있다.
dict = {}
S = "1325421134122427489"
for s in S:
if s in dict:
dict[s] += 1
else:
dict[s] = 1
그러나, 정의해야할 Dictionary가 여러 개인 경우, 코드가 길어지는 문제가 발생한다. 따라서, 이러한 상황에선 Counter 모듈을 활용할 것을 권장한다.
from collections import Counter
S1 = "1325421134122427489"
S2 = "85151221345232323"
S3 = "154643121549"
dict1 = Counter(S1)
dict2 = Counter(S2)
dict3 = Counter(S3)
① 리스트 순회
인덱스를 이용한 순회 > 원소 직접 순회
lst = [x for x in range(N)]
# <성능 개선 전>
for i in range(N):
print(lst[i])
# <성능 개선 후>
for i in lst:
print(i)
② if-elif-else 구문
if-elif > if-else
num = int(input())
# <성능 개선 전>
if num % 2 == 0:
pint('even')
elif num % 2 == 1:
print('odd')
# <성능 개선 후>
if num % 2 == 0:
pint('even')
else:
print('odd')
얼핏 보기에는 성능 상의 큰 차이가 없어보이는 로직이지만, 성능에 따라 차등 배점을 적용하는 문제에서는 성공/실패를 결정 짓기도 하는 중요한 요인이 된다. 그러므로, 처음부터 위와 같은 방식으로 코드를 짜는 습관을 들여두는 것이 좋다.