elevne's Study Note
Python 알고리즘 공부 (3: 구현) 본문
알고리즘 자체는 간단하지만 코드가 길어지거나 작성하기 까다로운 문제들이 있다. 이러한 문제들에는 모든 경우의 수를 주저 없이 다 계산하는 방식을 사용하는 완전탐색, 제시한 알고리즘을 한 단계씩 차례대로 직접 수행해야 하는 시뮬레이션 유형이 있다. (해당 책에서는 둘을 묶어 구현 파트에 넣어두었다) 두 유형에 해당하는 문제들을 하나씩 살펴보았다.
알고리즘 문제에서는 행렬을 많이 사용하게 된다. 2차원 행렬 위에서 캐릭터가 특정 규칙에 의해 좌표를 이동하는 등의 문제가 자주 출제된다고 한다. 아래는 하나의 예시 문제이다.
문제 1)
여행가 A는 N x N 크기의 정사각형 공간 위에 서 있다. 이 공간은 1 x 1 크기의 정사각형으로 나누어져 있다. 가장 왼쪽 위 좌표는 (1, 1)이며, 가장 아래 좌표는 (N, N) 에 해당한다. 여행가 A 는 상, 하, 좌, 우 방향으로 이동할 수 있으며 시작 좌표는 항상 (1, 1) 이다. 우리 앞에는 여행가 A 가 이동할 계획이 적힌 계획서가 놓여있다. 계획서에는 하나의 줄에 띄어쓰기를 기준으로 하여 L, R, U, D 중 하나의 문자가 반복적으로 적혀 있었다. 각 문자의 의미는 다음과 같다.
L: 왼쪽으로 한 칸 이동
R: 오른쪽으로 한 칸 이동
U: 위로 한 칸 이동
D: 아래로 한 칸 이동
이 때 여행가 A가 N x N 크기의 정사각형 공간을 벗어나는 움직임은 무시된다. 예를 들어 (1, 1) 의 위치에서 L 혹은 U 를 만나면 무시한다.
풀이 1)
아래와 같은 코드로 해결할 수 있다.
# N 입력 받기
n = int(input())
x, y = 1, 1
plans = input().split()
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]
move_types = ['L', 'R', 'U', 'D']
# 이동 계획을 하나씩 확인하기
for plan in plans:
# 이동 후 좌표 구하기
for i in range(len(move_types)):
nx = x + dx[i]
ny = y + dy[i]
# 공간을 벗어나는 경우 무시
if nx < 1 or ny < 1 or nx > n or ny > n:
continue
x, y = nx, ny
print(x, y)
문제 2)
정수 N 이 입력되면 00 시 00분 00초부터 N 시 59분 59초까지의 모든 시각 중에서 3이 하나라도 포함되는 모든 경우의 수를 구하는 프로그램을 작성한다. 예를 들어 1을 입력했을 때 다음은 3이 하나라도 포함되어 있으므로 세어야 하는 시각이다.
e.g., 00시 00분 03초 / 00시 13분 30초
풀이 2)
이 문제는 가능한 모든 시각의 경우를 하나씩 모두 세서 풀 수 있는 문제이다. 하루는 86,400 초이므로 00시 00분 00초부터 23시 59분 59초까지의 모든 경우는 86400 개이다. 따라서 단순히 시각을 1 씩 증가시키면서 3이 하나라도 포함되어 있는지를 확인하면 된다. 이러한 유형은 완전탐색(Brute Forcing) 문제유형이라고 불린다. 가능한 모든 경우의 수를 검사해보는 탐색 방법을 의미한다.
result = 0
for i in range(N + 1):
for j in range(60):
for k in range(60):
# 매 시각 안에 '3'이 포함되어 있다면 카운트 증가
# 두자리 숫자는 '3'이 포함되어 있는지 확인하기 어려우므로 문자열로 바꿔서 확인
# in 키워드, find() 함수를 사용하여 특정 문자열 포함되어 있는지 확인
if '3' in str(i) + str(j) + str(k):
result += 1
print(result)
문제 3)
행복 왕국의 왕실 정원은 체스판과 같은 8 x 8 좌표 평면이다. 왕실 정원의 특정한 한 칸에 나이트가 서있다. 나이트는 매우 충성스러운 신하로서 매일 무술을 연마한다. 나이트는 말을 타고 있기 때문에 이동을 할 때는 L자 형태로만 이동할 수 있으며 정원 밖으로는 나갈 수 없다. 나이트는 특정 위치에서 다음과 같은 2가지 경우로만 이동할 수 있다.
1. 수평으로 두 칸 이동한 뒤에 수직으로 한 칸 이동하기
2. 수직으로 두 칸 이동한 뒤에 수평으로 한 칸 이동하기
8 x 8 좌표 평면상에서 나이트의 위치가 주어졌을 때 나이트가 이동할 수 있는 경우의 수를 출력하는 프로그램을 작성한다. 왕실의 정원에서 행 위치를 표현할 때는 1부터 8로 표현하며 열 위치를 표현할 때는 a~h로 표현한다. (e.g., a1에 있을 때 이동할 수 있는 경우의 수는 2이다.)
풀이 3)
나이트의 8가지 경로를 하나씩 확인하며 각 위치로 이동이 가능한지 확인하는 문제이다.
# 현재 나이트의 위치 입력받기
input_data = input()
row = int(input_data[1])
# 아스키코드로 변환후 int 형으로 다시
column = int(ord(input_data[0])) - int(ord('a')) + 1
# 나이트가 이동할 수 있는 8가지 방향 정의
steps = [(-2, -1), (-1, -2), (1, -2), (2, -1), (2, 1), (1, 2), (-1, 2), (-2, 1)]
# 8가지 방향에 대하여 각 위치로 이동이 가능한지 확인
result = 0
for step in steps:
# 이동하고자 하는 위치 확인
next_row = row + step[0]
next_column = column + step[1]
# 해당 위치로 이동이 가능하다면 카운트 증가
if next_row >= 1 and next_row <= 8 and next_column >= 1 and next_column <= 8:
result += 1
print(result)
문제 4)
알파벳 대문자와 숫자(0~9)로만 구성된 문자열이 입력으로 주어진다. 이 때 모든 알파벳을 오름차순으로 정렬하여 이어서 출력한 뒤에 그 뒤에 모든 숫자를 더한 값을 이어서 출력한다.
풀이 4)
이 또한 마찬가지로 요구사항대로만 충실히 구현하면 된다. 문자열이 입력되었을 때 문자를 하나씩 확인하고 숫자인 경우 따로 합계를 계산, 알파벳은 별도의 리스트에 저장한다.
data = input()
result = []
value = 0
# 문자를 하나씩 확인하며
for x in data:
# 알파벳인 경우 결과 리스트에 삽입
if x.isalpha():
result.append(x)
# 숫자는 따로 더하기
else:
value += int(x)
# 알파벳을 오름차순으로 정렬
result.sort()
# 숫자가 하나라도 존재하는 경우 가장 뒤에 삽입
if value != 0:
result.append(str(value))
# 최종 결과 출력(리스트를 문자열로 변환하여 출력)
print(''.join(result))
Reference:
이것이 취업을 위한 코딩 테스트다
'Backend > Algorithm' 카테고리의 다른 글
Python 알고리즘 공부 (6: 이진탐색) (0) | 2023.01.20 |
---|---|
Python 알고리즘 공부 (5: 정렬) (0) | 2023.01.13 |
Python 알고리즘 공부 (4: DFS/BFS) (0) | 2023.01.08 |
Python 알고리즘 공부 (2: Greedy Algorithm) (0) | 2023.01.03 |
Python 알고리즘 공부 (1: 복잡도에 대하여) (0) | 2023.01.02 |