编写一个程序,通过已填充的空格来解决数独问题

编写一个程序,通过已填充的空格来解决数独问题。

一个数独的解法需 遵循如下规则

  1. 数字  1-9  在每一行只能出现一次。
  2. 数字  1-9  在每一列只能出现一次。
  3. 数字  1-9  在每一个以粗实线分隔的  3x3  宫内只能出现一次。

空白格用  '.'  表示。

250px-Sudoku-by-L2G-20050714.svg.png

一个数独。

250px-Sudoku-by-L2G-20050714_solution.svg.png

答案被标成红色。

Note:

  • 给定的数独序列只包含数字  1-9  和字符  '.'  。
  • 你可以假设给定的数独只有唯一解。
  • 给定数独永远是  9x9  形式的。

def ones(board):
    #填唯一值
    e=[str(x) for x in range(1,10)]
    hhs=[[x for x in e if x not in i] for i in board]   
    lhs=[[x for x in e if x not in i] for i in [[m[n] for m in board] for n in range(9)]]   
    ghs=[[x for x in e if x not in sum(i,[])] for i in [[n[p][o-3:o] for p in range(3)] for n in [board[m-3:m] for m in [3,6,9]] for o in [3,6,9]]]    while True:
        num=0
        for i in range(9):            for j in range(9):                if board[i][j]=='.':                
                    hlghss=[x for x in hhs[i] if x in lhs[j] and x in ghs[3*(i//3)+(j//3)]]                               
                    if len(hlghss)==1:
                        num+=1
                        board[i][j]=hlghss[0]
                        hhs[i].remove(hlghss[0])
                        lhs[j].remove(hlghss[0])
                        ghs[3*(i//3)+(j//3)].remove(hlghss[0])
        if num==0:
            hlghs={}            for i in range(9):                for j in range(9):                    if board[i][j]=='.':                
                        hlghs[(i,j)]=[x for x in hhs[i] if x in lhs[j] and x in ghs[3*(i//3)+(j//3)]]
            break
    return hlghs
    #填好后返回每个格子的候选值
  
def onechoice(b,hlg):
    #依次填候选值,只填一个,填好测试唯一值,如不能填满则重置board继续填
    board=[i.copy() for i in b]    for i in hlg:        for j in hlg[i]:
            board[i[0]][i[1]]=j           
            if len(ones(board))==0:                return i[0],i[1],j
                #返回填值信息
            board=[i.copy() for i in b]
def twochoice(b,hlg):
    #选行列宫互不相等的两格,依次填值,填好测试唯一值,如不能填满则重置board继续填
    board=[i.copy() for i in b]    for i in hlg:        for j in hlg:            if i[0]!=j[0] and i[1]!=j[1] and (3*(i[0]//3)+(i[1]//3))!=(3*(j[0]//3)+(j[1]//3)):
                for m in hlg[i]:                    for n in hlg[j]:
                        board[i[0]][i[1]]=m
                        board[j[0]][j[1]]=n                        if len(ones(board))==0:                            return i[0],i[1],m,j[0],j[1],n
                            #返回填值信息
                        board=[i.copy() for i in b]
                      
one=ones(board)             
if len(one)!=0:
    oc=onechoice(board,one)    if oc!=None:
        board[oc[0]][oc[1]]=oc[2]
        ones(board)    else:
        tc=twochoice(board,one)
        board[tc[0]][tc[1]]=tc[2]
        board[tc[3]][tc[4]]=tc[5]
        ones(board)

花了一天的时间来做这道题.在递归的地方卡了很久,始终不知道该怎么写,别人的代码给了我一些灵感.感谢!

注意一点:题目中说了数独有唯一解法,所以题目中给的所有数独都可解

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31551894/viewspace-2641862/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/31551894/viewspace-2641862/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值