PS/구현

[백준] No.1307 마방진 完

_빌런 2023. 9. 17. 02:35
# ---------- Import ----------
from math import ceil, floor
import sys
input = sys.stdin.readline


# ---------- Function ----------
def magic_sqaure_base(num):
    lst = [[0] * num for _ in range(num)]
    half = num // 2
    
    for r in range(0, num, half):
        for c in range(0, num, half):
            if c == 0:
                for i in range(half):
                    for j in range(half):
                        # 제 2사분면
                        if r == 0:
                            if c + j < floor(num / 4):
                                lst[r+i][c+j] = 3
                            else:
                                lst[r+i][c+j] = 0
                                
                        # 제 3사분면
                        else:
                            if c + j < floor(num / 4):
                                lst[r+i][c+j] = 0
                            else:
                                lst[r+i][c+j] = 3
                                
            else:
                for i in range(half):
                    for j in range(half):
                        # 제 1사분면
                        if r == 0:
                            if j < ceil(num / 4) + 1:
                                lst[r+i][c+j] = 2
                            else:
                                lst[r+i][c+j] = 1
                                
                        # 제 4사분면
                        else:
                            if j < ceil(num / 4) + 1:
                                lst[r+i][c+j] = 1
                            else:
                                lst[r+i][c+j] = 2
    
    mid = floor(num/4)
    lst[mid][0], lst[mid][mid] = lst[mid][mid], lst[mid][0]
    lst[half + mid][0], lst[half + mid][mid] = lst[half + mid][mid], lst[half + mid][0]
    
    return lst


def check_UPDN(lst, y, N):
    if 0 <= y < N:
        for i in range(N):
            if lst[i][y] == 0:
                return i, y
    else:
        return False


def check_LFTRGT(lst, x, N):
    if 0 <= x < N:
        for i in range(N):
            if lst[x][i] == 0:
                return x, i
    else:
        return False


def odd_magic_square(num: int) -> list:
    sqaure = [[0] * num for _ in range(num)]
    
    mid = num // 2
    current = 1
    
    x = num - 1
    y = mid
    
    sqaure[x][y] = current
    current += 1
    
    for _ in range(num**2 - 1):
        x += 1
        y += 1
        
        if x < 0 or x >= num or y < 0 or y >= num:
            if value := check_UPDN(sqaure, y, num):
                x, y = value[0], value[1]
                sqaure[x][y] = current
                current += 1
                continue
            elif value := check_LFTRGT(sqaure, x, num):
                x, y = value[0], value[1]
                sqaure[x][y] = current
                current += 1
                continue
            else:
                x -= 2
                y -= 1
                sqaure[x][y] = current
                current += 1
                continue
        
        elif 0 <= x < num and 0 <= y < num and sqaure[x][y] == 0:
            sqaure[x][y] = current
            current += 1
            continue
        
        elif 0 <= x < num and 0 <= y < num and sqaure[x][y]:
            x -= 2
            y -= 1
            sqaure[x][y] = current
            current += 1
            continue
            
    return sqaure


def even_magic_square(num: int) -> list:
    def mul_4(num: int) -> list:
        sqaure = [[0] * num for _ in range(num)]
        isExist = set()
        KEY = num // 4
        
        isOK = [[0] * num for _ in range(num)]
        for r in range(0, num, KEY):
            for c in range(0, num, KEY):
                if r == c or r + c == num - KEY:
                    for i in range(KEY):
                        for j in range(KEY):
                            isOK[r+i][c+j] = 1

        current = 0
        for r in range(num):
            for c in range(num):
                current += 1
                if isOK[r][c]:
                    sqaure[r][c] = current
                    isExist.add(current)
        
        all = set([i for i in range(1, num**2+1)])
        all -= isExist

        for r in range(num-1, -1, -1):
            for c in range(num-1, -1, -1):
                if sqaure[r][c] == 0:
                    sqaure[r][c] = all.pop()
        
        return sqaure
    
    
    def not_mul_4(num: int) -> list:
        using_value = odd_magic_square(num // 2)
        base = magic_sqaure_base(num)
        
        half = num // 2
        for x in range(0, num, half):
            for y in range(0, num, half):
                for i in range(half):
                    for j in range(half):
                        base[x+i][y+j] = base[x+i][y+j] * (num * num // 4) + using_value[i][j]
        
        return base
    
    
    if num % 4 == 0:
        return mul_4(num)
    else:
        return not_mul_4(num)


# ---------- Main ----------
N = int(input())

if N % 2 == 0:
    answer = even_magic_square(N)
else:
    answer = odd_magic_square(N)
    
for line in answer:
    print(*line)