''' 
找到一种将输入中的数字替换的方法,使得
1. 数字的出现次数符合原加法表
2. 可以通过原加法表交换行,列后得到 
然后在所有这种方法之中找到替换后的表格字典序最小的
'''
N = int(input())
li = list()
for i in range(N):
    li.append([int(x) for x in input().split()])
''' 
对于数字k, 出现 满足i+j = k的索引对的数量 次
k<=N: k-1次
k>N: 2N-k+1次
'''
def sum_table(N):
    return [[(i + j) for j in range(1, N+1)] for i in range(1, N+1)]
sumt = sum_table(N)
num_times = {i : i-1 if i<=N else 2*N-i+1 for i in range(2, 2*N+1)}
li_times = {}
for i in li:
    for j in i:
        if int(j) in li_times.keys():
            li_times[int(j)] += 1 
        else:
            li_times[int(j)] = 1
for i in li_times:
    li_times[i] = [n for n in num_times if li_times[i] == num_times[n]]
# sort the li_times
li_times = dict(sorted(li_times.items(), key=lambda item: item[0]))

def swap_dict(a, b, d:dict):
    d = d.copy()
    d[a], d[b] = d[b], d[a]
    return d
def swap_list(a, b, l:list):
    l = l.copy()
    # change a to b, b to a
    for i in range(len(l)):
        for j in range(len(l[i])):
            if l[i][j] == a:
                l[i][j] = b
            elif l[i][j] == b:
                l[i][j] = a
    return l
def valid_table(li):
    li = li.copy()
    '''
    行和列的跨度检查:
    每行的最大值与最小值差:对于每一行,最大值减最小值必须等于N-1。
    每列的最大值与最小值差:同样,每列的最大值减最小值也必须等于N-1。
    确定行置换σ和列置换τ:
    行置换σ:对于每行i,计算σ(i) = 该行最小值 - 1。所有σ(i)必须构成1到N的排列(无重复且覆盖所有值)。
    列置换τ:对于每列j,计算τ(j) = 该列最小值 - 1。所有τ(j)同样必须构成1到N的排列。
    元素验证:检查矩阵中的每个元素M[i][j]是否等于σ(i) + τ(j)。若所有元素均满足此条件,则矩阵有效。
    '''
    # 检查每行的最大值与最小值差是否为 N-1
    for row in li:
        min_val = min(row)
        max_val = max(row)
        if max_val - min_val != N - 1:
            return False
    
    # 检查每列的最大值与最小值差是否为 N-1
    for col in range(N):
        column = [li[row][col] for row in range(N)]
        min_val = min(column)
        max_val = max(column)
        if max_val - min_val != N - 1:
            return False
    
    # 确定行置换σ
    sigma = {}
    for i in range(N):
        min_val = min(li[i])
        sigma[i] = min_val - 1
    
    # 确定列置换τ
    tau = {}
    for j in range(N):
        column = [li[row][j] for row in range(N)]
        min_val = min(column)
        tau[j] = min_val - 1
    
    # 检查σ和τ是否为1到N的排列
    if sorted(sigma.values()) != list(range(1, N+1)) or sorted(tau.values()) != list(range(1, N+1)):
        return False
    
    # 验证每个元素是否等于 σ(i) + τ(j)
    for i in range(N):
        for j in range(N):
            if li[i][j] != sigma[i] + tau[j]:
                return False
    return True
''' 
li_times[i]为i替换前可能的原数字列表
3 4 2
5 2 3
6 3 5
original: {2: [2, 6], 3: [3, 5], 4: [4], 5: [3, 5], 6: [2, 6]}
changed : {2: [3, 5], 3: [4], 4: [2, 6], 5: [3, 5], 6: [2, 6]}
每一次交换a, b 会把a, b的列表交换
'''
def find_swaps(swaped, d=li_times):
    for i in d:
        if i not in d[i]:
            flag = False
            for num, val in d.items():
                if i in val and num not in val:
                    return find_swaps(swaped + [(i, num)], swap_dict(i, num, d))
    return swaped
swap_methods = find_swaps([], li_times)
for a, b in swap_methods:
    li = swap_list(a, b, li) 


'''
生成所有的 (j, 2N+2-j)的全组合, 存到to_swap[[]]里
'''
to_swap = []
for j in range(2, N + 1):
    for k in range(j, N + 1):
        '''添加从j到k中的所有数字及其对应'''
        to_swap.append([(l, 2*N+2-l) for l in range(j, k + 1)])

smallest = [[float('inf') for _ in range(N)] for _ in range(N)]
def less_than(l1, l2):
    for i in range(len(l1)):
        for j in range(len(l1[i])):
            if l1[i][j] < l2[i][j]:
                return True
            elif l1[i][j] > l2[i][j]:
                return False
    return False
for i in to_swap:
    lis = li.copy()
    for a, b in i:
        lis = swap_list(a, b, lis)
    if valid_table(lis): 
        if less_than(lis, smallest):
            smallest = [x.copy() for x in lis]

for i in smallest:
    print(' '.join([str(x) for x in i]))