구현이란?

머릿속에 있는 알고리즘을 소스코드로 바꾸는 과정이다. 모든 알고리즘 문제는 구현 문제라고 말할 수 있다. 그러나 흔히 구현 문제라고 하면 풀이는 쉬워보이지만 소스코드로 옮기기 어려운 문제를 말한다.

주의사항

  • 프로그래밍 문법
  • 라이브러리 사용 경험

풀이가 바로 떠올라도 문법을 정확하게 숙지하지 못하면 당연히 문제 풀기가 어려울 것이다. 또한 순열을 구하는 문제일 경우 반복문으로 해결할 수 있지만 파이썬 itertools와 같은 표준 라이브러리로 쉽게 해결할 수 있기때문에 라이브러리를 많이 알고있어야한다.

접근 방법

보통 구현 유형의 문제는 사소한 입력 조건이나 한 단계씩 수행해야하는 알고리즘을 문제에서 직접 제시하기 해주기 때문에 문제의 길이가 상당히 길다.
파이썬은 구현 난이도는 쉬운 편이지만 실행 시간이 오래 걸린다는 단점이 있어서 시간 초과의 우려도 있다. 그러나 Pypy3로 채점하면 pyhton의 문법은 동일하고 실행 속도가 더 빠르다.
결론은 Pypy3의 지원 여부를 확인 후, 지원한다면 Pypy3를 이용하자.

예제

상하좌우

문제

여행가 A가 N * N 크기의 정사각형 공간 위에 있고. 공간은 1 * 1크기의 정사각형으로 나누어져 있다. 가장 왼쪽 상단 좌표가 (1, 1)이고, 가장 오른쪽 하단 좌표는 (N, N)에 해당된다.

여행자는 상, 하, 좌, 우 방향으로만 이동할 수 있고, 시작 좌표는 항상 (1, 1)이다.

그리고 여행자 A가 이동할 계획이 적혀있는 계획서가 주어진다. 계획서는 띄어쓰기를 기준으로 L, R, U, D 중 하나의 문자가 반복적으로 주어진다.

각 문자의 의미는 다음과 같다.

  • L: 왼쪽으로 한 칸 이동
  • R: 오른쪽으로 한 칸 이동
  • U: 위로 한 칸 이동
  • D: 아래로 한 칸 이동

입력

첫째 줄에 공간의 크기를 나타내는 N이 주어진다(1<=N<=100)
둘째 줄에 여행가 A가 이동할 계획서 내용이 주어진다(1<=이동 횟수<=100)

출력

첫째 줄에 여행가 A가 최종적으로 도착할 지점의 좌표(X,Y)를 공백으로 구분하여 출력한다.

해결 방법

L,R,U,D에 따른 좌표 이동에 계산될 dx,dy를 선언하고 좌표값이 1보다 작거나 N보다 크면 나갔다고 판단하여 이동하지 않는다. 예를 들어 L은 왼쪽으로 1칸 이동하는 것이니 x값은 0, y값을 -1을 현재 좌표에서 더해주면 왼쪽으로 한칸 이동하게 된다.

import sys

N = int(sys.stdin.readline())
commands = sys.stdin.readline().split()
move = ['L','R','U','D']
x = 1
y = 1
dx = [0,0,-1,1]
dy = [-1,1,0,0]

for command in commands:
    for i in range(4):
        if command == move[i]:
            nx = x + dx[i]
            ny = y + dy[i]
    if nx < 1 or nx > N or ny < 1 or ny > N:
        continue
    x = nx
    y = ny

print(x,y)

시각

문제

정수 N이 입력되면 00시 00분 00초부터 N시 59분 59초까지의 모든 시각 중에서 3이 하나라도 포함되는 모든 경우의 수를 구하는 프로그램을 작성하라. 예를 들어 1을 입력했을 때 다음은 3이 하나라도 포함되어 있으므로 세어야 하는 시각이다.

  • 00시 00분 03초
  • 00시 13분 30초

반면에 다음은 3이 하나도 포함되어 있지 않으므로 세면 안 되는 시각이다.

  • 00시 02분 55초
  • 01시 27분 45초

입력

첫째 줄에 정수 N이 입력된다.(0<=N<=23)

출력

00시 00분 00초부터 N시 59분 59초까지의 모든 시각 중에서 3이 하나라도 포함되는 모든 경우의 수를 출력한다.

해결 방법

하루는 86,400초로 경우의 수가 100,000개도 되지 않는다. 3중 for문으로 0시00분00초~N+1시59분,59초까지 1씩 증가 하면서 3이 들어간 경우만 체크하면 된다. 즉 3시20분35초일때 체크 한다면 문자열 ‘032035’로 바꾸어 확인하면 된다.

import sys

N = int(sys.stdin.readline())
count = 0
for i in range(N+1):
    for j in range(60):
        for k in range(60):
            if '3' in str(i) + str(j) + str(k):\
                count += 1

print(count)

왕실의 나이트

문제

행복 왕국의 왕실 정원은 체스판과 같은 8 × 8 좌표 평면이다. 왕실 정원의 특정한 한 칸에 나이트가 서있다.
나이트는 매우 충성스러운 신하로서 매일 무술을 연마한다.
나이트는 말을 타고 있기 때문에 이동을 할 때는 L자 형태로만 이동할 수 있으며 정원 밖으로는 나갈 수 없다.
나이트는 특정 위치에서 다음과 같은 2가지 경우로 이동할 수 있다.

  1. 수평으로 두 칸 이동한 뒤에 수직으로 한 칸 이동하기
  2. 수직으로 두 칸 이동한 뒤에 수평으로 한 칸 이동하기

이처럼 8 × 8 좌표 평면상에서 나이트의 위치가 주어졌을 때 나이트가 이동할 수 있는 경우의 수를 출력하는 프로그램을 작성하라. 왕실의 정원에서 행 위치를 표현할 때는 1부터 8로 표현하며, 열 위치를 표현할 때는 a 부터 h로 표현한다.

입력

첫째 줄에 8x8 좌표 평면상에서 현재 나이트가 위치한 곳의 좌표를 나타내는 두 문자로 구성된 문자열이 입력된다. 입력 문자는 a1 처럼 열과 행으로 이뤄진다.

출력

첫째 줄에 나이트가 이동할 수 있는 경우의 수를 출력하시오.

해결 방법

상하좌우의 문제와 유사하다. 나이트가 움직일수 있는 모든 경우를 리스트에 선언하고 for문을 돌면서 현재 위치에서 이동했을때 좌표가 1보다 크거나 같고 8보다 작거나 같은 경우만 체크해주면 된다.

import sys

location = sys.stdin.readline()
row = int(location[1])
column = int(ord(location[0]) - ord('a')) + 1
count = 0
move = [[-2,1],[-2,-1],[2,1],[2,-1],[-1,2],[-1,-2],[1,2],[1,-2]]

for i in range(8):
    nx = row + move[i][0]
    ny = column + move[i][1]
    if nx < 1 or nx > 8 or ny < 1 or ny > 8:
        continue
    count += 1

print(count)

게임 개발

문제

현민이는 게임 캐릭터가 맵 안에서 움직이는 시스템을 개발 중이다. 캐릭터가 있는 장소는 1 X 1 크기의 정사각형으로 이뤄진 N X M 크기의 직사각형으로, 각각의 칸은 육지 또는 바다이다. 캐릭터는 동서남북 중 한 곳을 바라본다.

맵의 각 칸은 (A, B)로 나타낼 수 있고, A는 북쪽으로부터 떨어진 칸의 개수, B는 서쪽으로부터 떨어진 칸의 개수이다. 캐릭터는 상하좌우로 움직일 수 있고, 바다로 되어 있는 공간에는 갈 수 없다. 캐릭터의 움직임을 설정하기 위해 정해 놓은 매뉴얼은 이러하다.

  1. 현재 위치에서 현재 방향을 기준으로 왼쪽 방향(반시계 방향으로 90도 회전한 방향)부터 차례대로 갈 곳을 정한다.

  2. 캐릭터의 바로 왼쪽 방향에 아직 가보지 않은 칸이 존재한다면, 왼쪽 방향으로 횐전한 다음 왼쪽으로 한 칸을 전진한다. 왼쪽 방향에 가보지 않은 칸이 없다면, 왼쪽 방향으로 회전만 수행하고 1단계로 돌아간다.

  3. 만약 네 방향 모두 이미 가본 칸이거나 바다로 되어 있는 칸인 경우에는, 바라보는 방향을 유지한 채로 한 칸 뒤로 가고 1단계로 돌아간다. 단, 이때 뒤쪽 방향이 바다인 칸이라 뒤로 갈 수 없는 경우에는 움직임을 멈춘다.

현민이는 위 과정을 반복적으로 수행하면서 캐릭터의 움직임에 이상이 있는지 테스트하려고 한다. 메뉴얼에 따라 캐릭터를 이동시킨 뒤에, 캐릭터가 방문한 칸의 수를 출력하는 프로그램을 만드시오.

입력

첫째 줄에 맵의 세로 크기 N과 가로 크기 M을 공백으로 구분하여 입력한다. (3 <= N, M <= 50)
둘째 줄에 게임 캐릭터가 있는 칸의 좌표 (A, B)와 바라보는 방햔 d가 각각 서로 공백으로 구분하여 주어진다. 방향 d의 값으로는 다음과 같이 4가지가 존재한다.

  • 0: 북쪽
  • 1: 동쪽
  • 2: 남쪽
  • 3: 서쪽

셋째 줄부터 맵이 육지인지 바다인지에 대한 정보가 주어진다. N개의 줄에 맵의 상태가 북쪽부터 남쪽 순서대로, 각 줄의 데이터는 서쪽부터 동쪽 순서대로 주어진다. 맵의 외각은 항상 바다로 되어 있다.

  • 0 : 육지
  • 1 : 바다 처음에 게임 캐릭터가 위치한 칸의 상태는 항상 육지이다.

출력

첫째 줄에 이동을 마친 후 캐릭터가 방문 칸의 수를 출력한다.

해결방법

위의 문제와 마찬가지로 이동 방향을 리스트에 저장하여 좌표 값을 체크하여 문제를 풀면 된다. 또한 방문한 좌표를 체크하기 위한 별도의 2차원 리스트를 선언하여 방문 여부를 확인한다.

import sys

N, M = map(int, sys.stdin.readline().split())
visited = [[0] * M for _ in range(N)]
x, y, direction = map(int, sys.stdin.readline().split())
visited[x][y] = 1
dx = [-1,0,1,0]
dy = [0,1,0,-1]
arr = []
for i in range(N):
    arr.append(list(map(int,sys.stdin.readline().split())))

def turn_left():
    global direction
    direction -= 1
    if direction == -1:
        direction = 3
count = 1
turn_time = 0
while True:
    turn_left()
    nx = x + dx[direction]
    ny = y + dy[direction]
    #회전 후 정면에 방문하지 않은 칸이 있는 경우
    if visited[nx][ny] == 0 and arr[nx][ny] == 0:
        x = nx
        y = ny
        count += 1
        turn_time = 0
        continue
    # 회전 이후 정면이 방문 한 칸이거나 바다인 경우
    else:
        turn_time += 1
    # 네 방향 모두 갈 수 없는 경우
    if turn_time == 4:
        nx = x - dx[direction]
        ny = y - dx[direction]
        # 뒤로 갈 수 있다면 뒤로 이동
        if arr[nx][ny] == 0:
            x = nx
            y = ny
        # 뒤가 바다인 경우
        else:
            break
    turn_time = 0

print(count)

Comments