#学习到的知识:
#将一个列表list1行列进行颠倒:list2=[list(row) for row in zip(*list1)]
#回溯算法
#回溯算法的基本思想是通过尝试不同的选择,并在遇到无效选择时进行回溯,直到找到解决方案为止。它是一种深度优先搜索(DFS)的变种,通常通过递归来实现。
#基本步骤:
#选择:从问题的解空间中选择一个候选解,通常是从某个集合中选择一个元素。
#约束:检查候选解是否满足问题的约束条件。如果不满足,将候选解标记为无效。
#决策:根据约束条件的结果,决定是否接受候选解。如果候选解无效,需要回溯到前一步并尝试其他选择。
#重复:重复上述过程,尝试不同的选择,直到找到一个有效解或者确定无解为止。
#回溯:当发现当前路径无法得到解决方案时,回溯到前一步,撤销前一步的选择,然后继续尝试其他选择。

#回溯算法通常用于以下类型的问题:
#组合问题:找到满足一定条件的组合,如子集和问题、组合总和问题等。
#排列问题:找到满足一定条件的排列,如八皇后问题、旅行推销员问题等。
#搜索问题:在图或树中搜索路径,如单词搜索、路径问题等。

#时间复杂度:回溯算法的时间复杂度通常较高,因为它会尝试所有可能的选择。因此,在大规模问题上使用回溯可能不太实际。
#总之,回溯算法是一种强大的搜索算法,可用于解决各种组合、排列和搜索问题。但由于其指数级的复杂性,需要谨慎使用并考虑剪枝策略来提高效率。
#
#
def is_valid(list1, i,j,x):
    # 检查同一行是否有重复数字
    if x in list1[i]:
        return False

    # 检查同一列是否有重复数字
    list2=[list(row) for row in zip(*list1)]
    if x in list2[j]:
        return False

    # 检查同一个3x3小九宫格是否有重复数字
    for m in range((i//3)*3,((i//3)+1)*3):
        for n in range((j//3)*3,((j//3)+1)*3):
            if list1[m][n] == x:
                return False

    return True

def solve_sudoku(list1):
    for i in range(9):
        for j in range(9):
            if list1[i][j] == 0:
                for x in range(1, 10):
                    if is_valid(list1, i, j, x):
                        list1[i][j] = x
                        if solve_sudoku(list1):
                            return True
                        list1[i][j] = 0
                return False
    return True

# 读取数独输入
list1=[]
while True:
    try:
        list1.append([ int(x) for x in input().split(' ')])
    except:
        break

# 解决数独
if solve_sudoku(list1):
    for x in range(9):
        print(' '.join(str(y) for y in list1[x]),end='\n')
else:
    print("无解")