[백준] 소용돌이 예쁘게 출력하기

최동혁·2022년 12월 6일
0

백준

목록 보기
65/68

소용돌이 예쁘게 출력하기

소용돌이 예쁘게 출력하기

문제


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

이 모눈종이 전체를 양의 정수의 소용돌이 모양으로 채울 것이다. 일단 숫자 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가 주어진다.

출력


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

제한


  • -5000 ≤ r1, c1, r2, c2 ≤ 5,000
  • 0 ≤ r2 - r1 ≤ 49
  • 0 ≤ c2 - c1 ≤ 4

예제 입력 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

예제 입력 2

-2 2 0 3

예제 출력 2

13 30
12 29
11 28

예제 입력 3

-1 -2 -1 1

예제 출력 3

18  5  4  3

예제 입력 4

0 0 0 0

예제 출력 4

1

문제 해석

  • 크기가 무한인 배열이 있다.
  • 위에 문제 배열처럼 정해진 행과 열이 있다.
  • 0행 0열의 숫자는 1이며 소용돌이 모양으로 숫자가 증가한다.
  • 출력하고 싶은 행렬의 범위만큼 출력을 해줘야한다.
  • 출력은 그냥 출력하는 것이 아닌 가장 자릿수가 큰것을 기준으로 자릿수가 다르다면 공백으로 출력해야한다.

풀이

  • 1부터 시작하여 왼쪽 대각선 위로 증가하는 수열은 규칙이 있다.
    • 1, 5, 17, 37, 65
    • 각 수열의 차가 8씩 증가하게 된다.
  • 1부터 시작하여 오른쪽 대각선 밑으로 증가하는 수열도 규칙이 있다.
    • 2, 10, 26, 50, 82
    • 각 수열의 차가 8씩 증가하게 된다.
  • 1을 기준으로 왼쪽 위 대각선은 행과 열이 마이너스이다.
  • 1을 기준으로 오른쪽 밑 대각선은 행과 열이 플러스이다.
  • ans_minus, ans_plus로 5002개만큼 넣어준다.

규칙

  • y(열)의 절대값이 x(행)의 절대값보다 작거나 같을때까지 1씩 감소하거나 1씩 증가한다.
  • 절대값 x가 절대값 y보다 크다면?
    • x가 0보다 크다면?
      • 열이 증가하면서 1씩 증가한다.
    • x가 0보다 작으면?
      • 열이 증가하면서 1씩 감소한다.
    • 예를 들어 x가 -2이면 y는 -1 ~ 1는 전 열값보다 1씩 감소한다.
    • x가 2이면 y는 -1 ~ 1는 전 열값보다 증가한다.
    • 쉽게 생각하면 행을 기준으로 열이 증가할때에는 열의 절대값이 행의 절대값 범위 안에 있을 때 값을 찾아낼 수 있다.
  • 절대값 x가 절대값 y보다 작다면?
    • y가 0보다 크다면?
      • 행이 증가하면서 1씩 감소한다.
    • y가 0보다 작으면?
      • 행이 증가하면서 1씩 증가한다.
    • 예를 들어 y가 -2이면 x는 -1부터 1까지 전 행값보다 증가한다.
    • y가 2이면 x는 -1부터 1까지 전 행값보다 감소한다.
  • 절대값 x와 절대값 y가 같다면?
    • x가 0보다 크다면?
      • if x == y:
        • hurricane[x][y] = ans_minus[x - 1]
      • else:
        • hurricane[x][y] = ans_minus[x - 1] - abs(x - y)
    • x가 0보다 작으면?
      • if x == y:
        • hurricane[x][y] = ans_plus[x]
      • else:
        • hurricane[x][y] = ans_plus[x] - abs(x - y)
  • 위의 조건에서 x와 y가 0인 경우가 없다. x와 y가 0인 경우는 1이기 때문에 if hurricane[x][y] == 0이면 1로 바꾸어주면 된다.

출력

  • 가장 자릿수가 높은 수를 구한다.
  • 완전 탐색을 하면서 최대 자릿수보다 작다면 최대 자릿수와 현재 자릿수의 차이만큼 공백으로 출력해주고 값을 출력해준다.
import sys

ans_minus = []
ans_plus = []
a = 4

for i in range(5002):
    if i == 0:
        ans_minus.append(1)
        ans_plus.append(1)
    elif i == 1:
        ans_minus.append(5)
        ans_plus.append(2)
    else:
        a += 8
        ans_minus.append(ans_minus[-1] + a)
        ans_plus.append(ans_plus[-1] + a - 4)

r1, c1, r2, c2 = map(int, sys.stdin.readline().split())

x = abs(r1 - r2) + 1
y = abs(c1 - c2) + 1

hurricane = [[0] * y for _ in range(x)]


for i in range(x):
    for j in range(y):
        real_x = i + r1
        real_y = j + c1
        if abs(real_x) > abs(real_y):
            if real_x < 0:
                hurricane[i][j] = ans_minus[abs(real_x)] - abs(real_x - real_y)
            elif real_x > 0:
                hurricane[i][j] = ans_plus[abs(real_x) + 1] - abs(real_x - real_y) -1 
        elif abs(real_x) < abs(real_y):
            if real_y > 0:
                hurricane[i][j] = ans_plus[abs(real_y)] + abs(real_x - real_y) -1
            elif real_y < 0:
                hurricane[i][j] = ans_minus[abs(real_y)] + abs(real_x - real_y)
        elif abs(real_x) == abs(real_y):
            if real_x < 0:
                hurricane[i][j] = ans_minus[abs(real_x)] - abs(real_x - real_y)
            elif real_x > 0:
                hurricane[i][j] = ans_plus[abs(real_x) + 1] - abs(real_x - real_y) - 1 
        if hurricane[i][j] == 0:
            hurricane[i][j] = 1
max_num = 0
for i in range(x):
    max_hurricane = max(hurricane[i])
    max_num = max(max_hurricane, max_num)

max_num_len = len(str(max_num))

for i in range(x):
    for j in range(y):
        a = len(str(hurricane[i][j]))
        if a < max_num_len:
            b = " " * (max_num_len - a)
            b += str(hurricane[i][j])
            print(b, end = " ")
        else:
            print(hurricane[i][j], end = " ")
    print()

고찰

  • 단순한 규칙 문제였다.
profile
항상 성장하는 개발자 최동혁입니다.

0개의 댓글