728x90

문제

달팽이는 1부터 N*N까지의 숫자가 시계방향으로 이루어져 있다.

다음과 같이 정수 N을 입력 받아 N크기의 달팽이를 출력하시오.

 

예제

N이 3일 경우,



N이 4일 경우,
 

 

제약 사항

달팽이의 크기 N은 1 이상 10 이하의 정수이다. (1 ≤ N ≤ 10)

 

입력

가장 첫 줄에는 테스트 케이스의 개수 T가 주어지고, 그 아래로 각 테스트 케이스가 주어진다.

각 테스트 케이스에는 N이 주어진다.

 

출력

각 줄은 '#t'로 시작하고, 다음 줄부터 빈칸을 사이에 두고 달팽이 숫자를 출력한다.

(t는 테스트 케이스의 번호를 의미하며 1부터 시작한다.)

 

예제

[입력] [출력]
2
3
4
#1
1 2 3
8 9 4
7 6 5
#2
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7

 

문제 해결 방법

  • 2차원 리스트를 만든 후, 규칙을 찾아 방향을 바꾸며 숫자를 채워넣는 문제이다.
  • 우선 @0@으로 채워진 N × N 크기의 2차원 리스트를 생성한다.
matrix = [[0] * N for _ in range(N)]

 

  • 그리고 방향의 변화를 나타내기 위한 리스트 2개(x축 방향(@dir_x@), y축 방향(@dir_y@))를 생성해준다.
# x좌표와 y좌표를 이동하기 위한 방향 설정 (오른쪽, 아래쪽, 왼쪽, 위쪽)
dir_x = [1, 0, -1, 0]    # x축 방향 
dir_y = [0, 1, 0, -1]    # y축 방향

 

  • 예를 들어, 아래와 같이 오른쪽 → 아래쪽 → 왼쪽 → 위쪽으로 이동할 경우, @M[y][x]@에서 @x@의 변화를 확인해보면 오른쪽으로 이동할 때 @+1@, 아래쪽으로 이동할 때 @+0@, 왼쪽으로 이동할 때 @-1@, 위쪽으로 이동할 때 @+0@임을 확인할 수 있다.
  • 또한 @y@의 변화를 확인해보면 오른쪽으로 이동할 때 @+0@, 아래쪽으로 이동할 때 @+1@, 왼쪽으로 이동할 때 @+0@, 위쪽으로 이동할 때 @-1@임을 확인할 수 있다.
  x↑ (+0) y↑ (-1)    
  M[0][0] M[0][1] M[0][2] x→ (+1)
y← (+0) M[1][0] M[1][1] M[1][2] y→ (+0)
x← (-1) M[2][0] M[2][1] M[2][2]  
    y↓ (+1) x↓ (+0)  

 

  • 초기 위치와 방향을 설정해준다. 
    • @x@와 @y@는 2차원 리스트의 인덱스 값을 의미한다.
    • @dir@은 1차원 리스트의 인덱스 값을 의미한다.
# 초기 위치와 방향 설정하기
x = 0
y = 0
dir = 0

 

  • 본격적으로 알고리즘을 작성하도록 한다.
  • @matrix[y][x]@에는 @1@부터 @N@까지의 숫자가 각각 넣어지도록 한다.
  • 여기에서 2차원 리스트의 인덱스 값인 @x@와 @y@ 값에 변화를 줌으로써, 달팽이 모양으로 숫자가 담기도록 해줄 것이다.
matrix[y][x] = num

 

  • for 문을 한 번 작업할 때마다(한 스텝이 끝날 때마다) 다음의 x좌표(@next_x@)와 y좌표(@next_y@)를 설정해주어야 한다.
next_x = x + dir_x[dir]
next_y = y + dir_y[dir]

 

  • @x@ 좌표와 @y@ 좌표가 업데이트 될 수 있도록 한다.
  • 만약 한 스텝을 마친 후, 다음의 x좌표(@next_x@)와 y좌표(@next_y@)가 N × N 리스트 에 있고, 해당 위치에 있는 리스트 안의 값이 @0@일 경우, 다음 스텝의 2차원 리스트의 x 좌표와 y 좌표를 각각 위에서 계산한 다음 좌표로 설정한다. (@x, y = next_x, next_y@)
  • 만약 다음의 x좌표(@next_x@)와 y좌표(@next_y@)가 N × N 리스트 밖에 있게될 경우 방향(@dir@)을 바꿔줘야 한다.
    • 오른쪽 → 아래쪽 → 왼쪽 → 위쪽 순서로 방향이 바뀌므로 위에서 미리 생성한 @dir_x@ 리스트와 @dir_y@ 리스트를 활용하여 방향을 바꿔준다.
    • 방향(@dir@)은 상/하/좌/우 4개(인덱스 @0@부터 @3@까지)만 나오도록 @%@ 연산자를 사용하여 반복되도록 한다.
# x, y 좌표 업데이트
if 0 <= next_x < N and 0 <= next_y < N and matrix[next_y][next_x] == 0:    # 범위 안에 있을 경우
    x = next_x
    y = next_y
else:     # 범위 밖에 있을 경우
    dir = (dir + 1) % 4
    x = x + dir_x[dir]
    y = y + dir_y[dir]

 

코드

def solution(N):
    # 0으로 채워진 N x N 크기의 배열 생성
    matrix = [[0] * N for _ in range(N)]

    # x좌표와 y좌표를 이동하기 위한 방향 설정 (오른쪽, 아래쪽, 왼쪽, 위쪽)
    dir_x = [1, 0, -1, 0]    # x축 방향 
    dir_y = [0, 1, 0, -1]    # y축 방향

    # 초기 위치와 방향 설정하기
    x = 0
    y = 0
    dir = 0

    for num in range(1, (N * N) + 1):
        matrix[y][x] = num

        next_x = x + dir_x[dir]
        next_y = y + dir_y[dir]

        # x, y 좌표 업데이트
        if 0 <= next_x < N and 0 <= next_y < N and matrix[next_y][next_x] == 0:    # 범위 안에 있을 경우
            x = next_x
            y = next_y
        else:     # 범위 밖에 있을 경우
            dir = (dir + 1) % 4
            x = x + dir_x[dir]
            y = y + dir_y[dir]
    
    return matrix

T = int(input())

for test_case in range(1, T + 1):
    N = int(input())

    matrix = solution(N)

    print(f"#{test_case}")
    for row in matrix:
        print(" ".join(map(str, row)))

 

참고

  • 난이도: D2
728x90