반응형

문제

크기가 무한인 정사각형 모눈종이가 있다. 모눈종이의 각 정사각형은 행과 열의 쌍으로 표현할 수 있다.

이 모눈종이 전체를 양의 정수의 소용돌이 모양으로 채울 것이다. 일단 숫자 1을 0행 0열에 쓴다. 그리고 나서 0행 1열에 숫자 2를 쓴다. 거기서 부터 소용돌이는 반시계 방향으로 시작된다. 다음 숫자는 다음과 같이 채우면 된다.

    -3 -2 -1  0  1  2  3
    --------------------
-3 |37 36 35 34 33 32 31
-2 |38 17 16 15 14 13 30
-1 |39 18  5  4  3 12 29
 0 |40 19  6  1  2 11 28
 1 |41 20  7  8  9 10 27
 2 |42 21 22 23 24 25 26
 3 |43 44 45 46 47 48 49

이 문제는 위와 같이 채운 것을 예쁘게 출력하면 된다. r1, c1, r2, c2가 입력으로 주어진다. r1, c1은 가장 왼쪽 위 칸이고, r2, c2는 가장 오른쪽 아래 칸이다.

예쁘게 출력한다는 것은 다음과 같이 출력하는 것이다.

  1. 출력은 r1행부터 r2행까지 차례대로 출력한다.
  2. 각 원소는 공백으로 구분한다.
  3. 모든 행은 같은 길이를 가져야 한다.
  4. 공백의 길이는 최소로 해야 한다.
  5. 모든 숫자의 길이(앞에 붙는 공백을 포함)는 같아야 한다.
  6. 만약 수의 길이가 가장 길이가 긴 수보다 작다면, 왼쪽에서부터 공백을 삽입해 길이를 맞춘다.

입력

첫째 줄에 r1, c1, r2, c2가 주어진다. 모두 절댓값이 5000보다 작거나 같은 정수이고, r2-r1은 0보다 크거나 같고, 49보다 작거나 같으며, c2-c1은 0보다 크거나 같고, 4보다 작거나 같다.

출력

r2-r1+1개의 줄에 소용돌이를 예쁘게 출력한다.

예제 입력 1 복사

-3 -3 2 0

예제 출력 1 복사

37 36 35 34
38 17 16 15
39 18  5  4
40 19  6  1
41 20  7  8
42 21 22 23

나의 풀이

처음에 r1,r2,c1,c2의 최댓값을 구하고, 최댓값의 2배에 1을 더한만큼의 소용돌이를 모두 그린후 필요한 부분만 출력을 하는 방법으로 풀이를 하였으나 r1,r2,c1,c2의 절댓값이 5000보다 작거나 같은 정수로 메모리 초과가 나올 수 밖에 없었다... 그래서 생각한 방법이 소용돌이는 모두 돌되 지정된 부분만큼만 배열을 만들어놓고 해당 부분에 도달할때만 배열에 저장하게끔 풀이를 하였다.

우선 소용돌이를 그리는 방법은 왼쪽으로 턴을 2번째 할때마다 증가하는 수가 한개씩 증가한다는 규칙이 있었다. 예를들면 처음 1로 시작해 오른쪽으로 1만큼 간 뒤 위로 턴, 위쪽으로 1만큼 간 뒤 왼쪽으로 턴, 2번 턴을 한 뒤 부터는 왼쪽으로 2만큼 이동 아래로 턴, 아래로 2만큼 이동...과 같은 식이다. 따라서 왼쪽으로 이동하는 방향으로 턴을 할 경우, 오른쪽으로 이동하는 방향으로 턴을 할 경우에 이동하는 수가 1만큼 증가하는 것이다. 따라서 한 방향에서 움직이는 횟수를 cnt 로 두고 한 방향에서 움직여야할 횟수를 dcnt로 두고 두 개의 변수가 같아질 경우 cnt 를 다시 0으로 초기화함과 동시에 방향이 왼쪽, 오른쪽을 향하는 경우 dcnt 를 1만큼 증가시켜주었다.

이를 반복문을 통해 반복을 하는데 끝남의 여부는 지정된 부분의 배열이 모두 차는 상황을 찾는 것이다. 이는 배열의 원소 개수를 할당하는 변수를 두고 이 변수가 0보다 클때 계속 반복하는 방식으로 구현하였다.

y가 r1과 r2 사이에, x가 c1과 c2사이에 존재한다면 위에서 만들어놓은 배열에 저장을 할 수 있는 상태라는 의미로 y-r1, x-c1 만큼 인덱스를 조정하여 저장하고 원소 수를 할당해놓은 변수를 1만큼 감소시켜주었다.

이쁘게 출력하는 방법은 배열에 담기는 수 중 최댓값의 자리수를 찾고 그 자리수만큼 출력 서식을 지정해주었다. python3에서 서식문자를 사용해 자리수를 지정할 수도 있지만, rjust() 를 사용해서도 지정할 수 있었다. 아래 코드를 보면 쉽게 이해할 수 있다.


코드

# 소용돌이 예쁘게 출력하기

dx = [1, 0, -1, 0]
dy = [0, 1, 0, -1]

r1, c1, r2, c2 = map(int, input().split())

board = [[0] * (c2-c1+1) for _ in range(r2-r1+1)]
number_of_board = (c2-c1+1) * (r2-r1+1)

y = x = 0
num = 1
cnt = 0
dcnt = 1
d = 0

while number_of_board > 0:
    if r1 <= y <= r2 and c1 <= x <= c2:
        number_of_board -= 1
        board[y - r1][x - c1] = num
        max_num = num
    num += 1
    cnt += 1

    y = y + dy[d]
    x = x + dx[d]

    if cnt == dcnt:
        cnt = 0
        d = (d+3) % 4
        if d == 0 or d == 2:
            dcnt += 1


max_num_len = len(str(max_num-1))
for i in range(r2-r1+1):
    for j in range(c2-c1+1):
        print(str(board[i][j]).rjust(max_num_len), end= ' ')
    print()
반응형

BELATED ARTICLES

more