[Algorithm 이론] 구현(Implementation)
머릿속에 있는 알고리즘을 소스코드로 바꾸는 과정인 구현(Implementation)에 대해서 알아보자.
구현
: 머릿속에 있는 알고리즘을 소스코드로 바꾸는 과정
- 완전 탐색 : 모든 경우의 수를 주저 없이 다 계산하는 해결 방법
- 시뮬레이션 : 문제에서 제시한 알고리즘을 한 단계씩 차례대로 직접 수행
[구현 시 고려해야할 메모리 제약 사항]
- 파이썬에서 리스트 크기
- 파이썬에서 여러 개의 변수를 사용할 때 리스트를 이용
-> BUT!! 메모리 제한있음 - 수백만 개 이상의 데이터 처리하는 문제 -> 메모리 제한 염두해야함.
- 크기가 1,000만 이상인 리스트가 있다면 메모리 제한 걸릴 수 있음
- 파이썬에서 여러 개의 변수를 사용할 때 리스트를 이용
| 데이터 개수(리스크 길이) | 메모리 사용량 |
|---|---|
| 1,000 (천) | 약 4KB |
| 1,000,000 (백만) | 약 4MB |
| 10,000,000 (천만) | 약 40MB |
예제 4-1. 상하좌우 (시뮬레이션 문제)
-
여행가 A는 (N * N) 크기의 정사각형 공간 위에 서 있다. 이 공간은 (1 * 1) 크기의 정사각형들로 나누어져 있다.
- 가장 왼쪽 위 좌표 = (1, 1) / 가장 오른쪽 아래 좌표 (N, N)
- A는 상, 하, 좌, 우 이동 가능, 시작 좌표는 항상 (1, 1)
- L : 왼쪽으로 / R : 오른쪽으로 / U : 위쪽으로 / D : 아래쪽으로 한 칸 이동
- $N*N$ 크기의 공간을 벗어나는 움직임 무시
- 계획서가 주어 졌을 때 A가 최종적으로 도착할 지점의 좌표 출력
[입력 조건]
첫째 줄 : 공간의 크기를 나타내는 N이 주어진다
둘째 줄 : A가 이동할 계획서 내용
[출력 조건]
A가 최종적으로 도착할 지점의 좌표를 공백으로 구분하여 출력
풀이-1
n = int(input())
plans = input().split()
# 시작 지점
x, y = 1, 1
# LRUD 이동 방향
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]
move_type = ['L', 'R', 'U', 'D']
# 계획서에 따른 이동
for plan in plans:
i = move_type.index(plan) # 어떤 이동인지 찾기
nx = x + dx[i]
ny = y + dy[i]
# 공간 벗어나는 경우 pass
if nx < 1 or nx > n or ny < 1 or ny > n:
# continue를 함으로써 벗어나는 경우 '이동한 것을 적용'을 실행하지 않고 다음 for문 실행
continue
# 이동한 것을 적용
x, y = nx, ny
print(x, y)
3 4
풀이-2
n = int(input())
plans = input().split()
x, y = 1, 1
nx, ny = 1, 1
# 위 아래가 x좌표 -+1
# 좌 우가 y좌표 -+1
for plan in plans:
if plan == 'R':
ny = y + 1
if plan == 'L':
ny = y - 1
if plan == 'U':
nx = x - 1
if plan == 'D':
nx = x + 1
if ny < 1 or ny > n or nx < 1 or nx > n:
nx, ny = x, y
x, y = nx, ny
print(x, y)
3 4
예제 4-2. 시각 (완전 탐색 문제)
- 정수 N이 입력되면 00시 00분 00초부터 N시 59분 59초까지의 모든 시각 중 3이 하나라도 포함되는 모든 겨우의 수를 구하는 프로그램 작성
[입력조건]
첫째 줄 : 정수 N 입력 ($0<=N<= 23$)
[출력 조건]
00시 00분 00초 ~ N시 59분 59초까지의 모든 시각중 3이 하나라도 포함되는 모든 경우의 수 출력
풀이
def count_3(h):
result = 0
for i in range(h+1): #시
for j in range(60): # 분
for k in range(60): # 초
if '3' in str(i) + str(j) + str(k):
result += 1
return result
count_3(5)
11475
실전문제 4-1. 왕실의 나이트
- 왕실 정원 = 체스판과 같은 $8*8$ 좌표 평면
- 특정한 한 칸에 나이트가 서 있음 -> L자 형태로만 이동(정원 밖으로 나갈 수 없음)
- 수평으로 두 칸 이동한 뒤에 수직으로 한 칸 이동
- 수직으로 두 칸 이동한 뒤에 수평으로 한 칸 이동
- 나이트의 위치가 주어졌을 때 나이트가 이동할 수 있는 경우의 수를 출력하는 프로그램 작성
[입력 조건]
첫째 줄 : 현재 나이트가 위치한 고의 좌표를 나타대는 문자열 입력(열, 행)
[출력 조건] 나이트가 이동할 수 있는 경우의 수 출력
풀이
input_data = input()
first_loc = int(ord(input_data[0])) - int(ord('a')) + 1 # 문자열을 수치화(유니코드 정수)하기 위해
# int(ord('a')) = 97
# (1, 1)이 가장 작은 좌표이므로 마지막에 +1
second_loc = int(input_data[1])
# 움직일 수 있는 경우의 수 = 8 가지
moves = [(2, 1), (2, -1), (-2, 1), (-2, -1) , (-1, 2), (1, 2), (-1, -2), (1, -2)]
result = 0
for move in moves:
first_loc_move = first_loc + move[0]
second_loc_move = second_loc + move[1]
if 0 < first_loc_move < 9 and 0 < second_loc_move < 9: # 좌표가 범위 안에 있으면
result += 1
print(result)
2
실전문제 4-2. 게임 개발
- 게임 캐릭터가 맵 안에서 움직이는 시스템 개발
- 맵은 $N*M$ 크기의 직사각형, 각각의 칸은 육지 or 바다
- 바다로 된 곳은 이동 불가
- 상하좌우로 움직일 수 있음
- 캐릭터는 동서남북 중 한 곳을 바라본다.
- 각 칸 (A, B) : A = 북쪽으로부터 떨어진 칸의 개수 / B = 서쪽으로부터 떨어진 칸의 개수
- 캐릭터 움직임 메뉴얼
- 현재 위치에서 현재 방향을 기준으로 왼쪽 방향(반시계 방향으로 90도 회전한 방향)부터
차례대로 갈 곳을 정한다. - 캐릭터 바로 왼쪽 방향에 아직 가보지 못한 칸이 존재한다면,
왼쪽 방향으로 회전한 다음 왼쪽으로 한칸 전진- 왼쪽 방향에 가보지 않은 칸이 없다면 왼쪽 방향으로 회전만하고 1)로 돌아감
- 네 방향 모두 이미 가본 칸이거나 바다로 되어 있는 칸인 경우,
바라보는 방향 유지한 채로 한칸 뒤로가고 1)로 돌아감- 뒤쪽 방향이 바다이면 stop!
- 현재 위치에서 현재 방향을 기준으로 왼쪽 방향(반시계 방향으로 90도 회전한 방향)부터
[입력 조건]
첫째 줄: 맵의 세로크기 N과 가로크기 M을 공백으로 구분하여 입력 (3 <= 3, M <= 50>)
둘째 줄: 캐릭터가 있는 좌표와 바라보고 있는 뱡항 공백으로 구분하여 입력 (북:0/동:1/남:2/서:3)
셋째 줄: 맵이 육지 안지 바다인지에 대한 정보 (맵 외곽은 항상 바다, 육지:0/바다:1)
[출력 조건]
캐릭터가 방문한 칸의 수
Tip!!
- 문제에서 요구하는 내용을 오류 없이 성실하게 구현
- 방향을 설정해서 이동하는 문제 : dy, dy라는 별로 리스트를 만들어 방향을 정하는 것이 효과적
풀이
# n, m : 행의 수, 열의 수
# x, y, direction : 현재 좌표 , 바라보고 있는 방향
n, m = map(int, input().split())
x, y, direction = map(int, input().split())
# 방문한 위치 저장하기 위한 배열
d = [[0] * m for _ in range(n)]
# 현재 위치는 방문했으므로 1로 변경(0이면 방문안한 곳)
d[x][y] = 1
# 실제 맵 정보 가져오기 ----- [[1, 0, 0, 0], [0, 1, 1, 0]] 2차 배열 형태임.
array = []
for i in range(n):
array.append(list(map(int, input().split())))
# 방향을 정의해야 함
# 북, 동, 남, 서 (문제에 이 순서대로 나옴) - 이 순서대로 direction 지정할 예정
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]
# 왼쪽 회전 (조건에 다라서 왼쪽으로 회전하는 경우 있음 - 시뮬레이션 가기전 미리 함수로 생성)
def turn_left():
global direction
direction += -1
if direction == -1:
direction = 3
# 시뮬레이션 start
turn_time = 0 # 4가 되면 뒤로가야함.
count = 1 # 방문한 칸 수 (현재 있는 곳도 방문했으므로 1부터 시작)
while True:
# 왼쪽 회전
turn_left()
nx = x + dx[direction]
ny = y + dx[direction]
# 회전하고 정면에 가보지 않은 칸 존재 = 이동
if d[nx][ny] == 0 and array[nx][ny] == 0:
d[nx][ny] = 1 # 이동 했으니 이동한 좌표는 방문한 곳 = 1
# 현재 위치 초기화
x = nx
y = ny
count += 1
turn_time = 0 # 초기화
continue
# 회전하고 정면에 가보지 않은 칸 없거나 바다 = 왼쪽 회전한 채로 다시 처음으로
else:
turn_time += 1
if turn_time == 4:
# 뒤로 이동했다 가정
nx = x - dx[direction]
ny = y - dy[direction]
# 뒤로 갈 수 있음 뒤로 이동
if array[nx][ny] == 0:
x = nx
y = ny
# 뒤로 가지 못하는 상황
else:
break
turn_time = 0
print(count)
3
댓글남기기