Programming Languages/Python

[백준] 1022번: 소용돌이 예쁘게 출력하기 Python

minjiwoo 2023. 3. 14. 15:23
728x90

https://www.acmicpc.net/problem/1022

 

1022번: 소용돌이 예쁘게 출력하기

첫째 줄에 네 정수 r1, c1, r2, c2가 주어진다.

www.acmicpc.net

어렵다.. 출력할 부분만 어떻게 만들어줘야하는지 감이 잘 안와서 어려웠던 문제이다. 또한 모눈종이에서 생각하는 좌표와 실제로 출력해줄 부분에서의 좌표 변환이 어려웠다 (board[x - r1][y - c1]) ㅠㅠ 

문제 푸는 아이디어 

1. 구현 자체는 소용돌이를 모두 구현한다고 생각하되, 배열은 출력할 크기인 (c2-c1+1) * (r2-r1+1)으로만 초기화해준다. 

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

그리고 x, y 가 board 범위에 속하는 경우에만 num 을 board에 기록한다. 

x, y = 0, 0으로 초기화하여 생각했으므로, 실제 board에서의 위치는 board[x - r1][y - c1] 인 것에 주의해야 한다 !!!! 

 2. dx, dy 방향표는 우 -> 상 -> 좌 -> 하 로 만들어 주었다 여기서 index 0 은 우방향

3. 소용돌이 규칙은  우,상 / 좌좌, 하하 / 우우우, 상상상 ... 직접 적으면서 알아냈다 (낯이 익다)

- 한 방향을 length 만큼 반복한다
- 같은 length를 사용하는건 2번반복하고, length 길이를 하나씩 늘려준다. 

4. 소용돌이 방향 전환은 dx, dy 를 이용해서 dir 를 배열의 인덱스라고 생각하고 1씩 증가시킨 후 4로 나눈 나머지를 이용하였다. 

5.  num 은 1씩 증가시켜준다. 

6. num 을 실제 board에 표기했다면  count_max_num 을 num으로 갱신한다. count_max_num 값은 나중에 예쁘게 출력할 때 길이가 필요해서 저장해 둘 필요가 있다 

# python 통과 못함 pypy만
import sys
input = sys.stdin.readline
r1, c1, r2, c2 = map(int, input().split())

# 시계 반대 방향 우 상 좌 하
# 우 or 좌 방향에서 칸수 1 증가함

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

x, y = 0, 0 # 시작점
size = (c2-c1+1) * (r2-r1+1)
# 칸 채우기
length = 1
dir = 0
num = 1 # 칸에 채울 숫자
count_max_num = 0 # 실제로 넣은 숫자중에 가장 큰 숫자
while size > 0:
    # 같은 length 2번 반복 후, length + 1
    for i in range(2):
        for j in range(length):
            if r1 <= x <= r2 and c1 <= y <= c2: # 칸에 넣을 수 있으면 기록 아니면 버리기
                board[x - r1][y - c1] = num
                count_max_num = num
                size -= 1
            x += dx[dir]
            y += dy[dir]
            num += 1

        dir = (dir+1) % 4 # 방향 전환
    length += 1

blank = len(str(count_max_num))

for i in range(r2 - r1 + 1):
    for j in range(c2 - c1 + 1):
        print(str(board[i][j]).rjust(blank), end=" ")
    print()
728x90