求解四宫数独

28 篇文章 1 订阅
16 篇文章 0 订阅

#!/usr/bin/python3
#文件:求解四宫数独
#作者:巧若拙
#日期:2019年2月19日
'''
四宫数独规则:在4x4的格子中,根据已知数字,推理出所有剩余空格的数字,
并满足每一行,每列,每一个宫内均含1到4的数字并且不重复,每道数独有且仅有唯一答案。
'''
def four_palace_sudoku(a, n):
    def answer(r, c):
        t = [0] * (n + 1)
        for i in range(n):#标记同行同列的已有数字
            t[a[r][i]], t[a[i][c]] = 1, 1
        s = int(n ** 0.5)#每个宫的尺寸
        #确定a[r][c]所在宫的起始行列坐标
        br, bc = (r // s) * s, (c // s) * s
        for i in range(br, br+s):#标记同宫已有数字
            for j in range(bc, bc+s):
                t[a[i][j]] = 1
        k = 0
        for i in range(1, n+1):
            if t[i] == 0:
                num = i
            else:
                k += 1 #累计已有数字
        if k == n - 1: #a[r][c]的值确定为num
            return num
        else:
            return 0
        
    flag = False
    while not flag:
        flag = True
        for r in range(n):
            for c in range(n):
                if a[r][c] == 0:
                    a[r][c] = answer(r, c)
                    if a[r][c] > 0:
                        flag = False
                        print(f'a[{r}][{c}] = {a[r][c]}')

def check(a, n, r, c, num):#判断a[r][c]能否取数字num
    for i in range(n):#判断同行同列是否已有数字num
        if a[r][i] == num or a[i][c] == num:
            return False
    s = int(n ** 0.5)#每个宫的尺寸
    #确定a[r][c]所在宫的起始行列坐标
    br, bc = (r // s) * s, (c // s) * s
    for i in range(br, br+s):#判断同宫是否已有数字num
        for j in range(bc, bc+s):
            if a[i][j] == num:
                return False
    return True

def show(a, n):#输出结果
    for i in range(n):
        for j in range(n):
            print(a[i][j], end=" ")
        print()
    print()
    
def four_palace_sudoku2(a, n):
    def dfs(r, c):
        nonlocal count
        if r == n: #所有位置都填好了,输出解 
            count += 1
            print(f'{count}:')
            show(a, n)
        elif a[r][c] > 0:#该位置的值已确定,直接下一步
            if c < n - 1:#确定下一个位置的坐标
                tr, tc = r, c + 1
            else:
                tr, tc = r + 1, 0
            dfs(tr, tc)
        else:
            for i in range(1, n+1):#枚举本位置的可能取值
                if check(a, n, r, c, i):#如果可以取数字i,递归进入下一层
                    a[r][c] = i
                    if c < n - 1:
                        tr, tc = r, c + 1
                    else:
                        tr, tc = r + 1, 0
                    dfs(tr, tc)
            a[r][c] = 0 #所有数字都取过了,恢复原值,回溯
            
    count = 0
    if a[0][0] > 0:
        dfs(0, 1)
    else:
        for i in range(1, n+1):
            if check(a, n, 0, 0, i):
                a[0][0] = i
                dfs(0, 1)
                a[0][0] = 0
                

a = [[0,4,0,0],
     [0,0,0,0],
     [0,0,3,0],
     [0,2,0,4]]
n = 4
show(a, n)
four_palace_sudoku(a, n)
show(a, n)

a = [[0,1,0,0],
     [0,0,0,0],
     [0,0,3,0],
     [0,2,0,0]]
n = 4
show(a, n)
four_palace_sudoku2(a, n)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Python中求解(Sudoku)通常会使用回溯算法或启发式搜索策略。以下是一个简单的概述: 1. **回溯算法**:这是一种递归的方法,从第一个空格开始,尝试填入数字1到9,然后检查每一行、每一列和每一个宫格(3x3的小九宫格)是否都包含这9个数字一次。如果发现冲突,则回溯到上一步,尝试下一个数字。这个过程一直持续到找到一个合法的数解决方案或者所有可能的数字都尝试过仍无解。 2. **启发式搜索**:如使用A*搜索,会优先填充那些规则更明确的位置(如行、列、宫格已完全填满的区域),并在搜索过程中维护一个启发式函数(如最小剩余数法),帮助找到最快接近解决方案的状态。 在Python中,可以使用`numpy`库来创建和操作二维数组,`pandas`处理数据结构,还有自定义的数据结构(如`dict`或`set`)来存储候选数字。下面是一个简单的回溯算法示例: ```python import numpy as np def solve_sudoku(board): empty_cells = find_empty_cells(board) if not empty_cells: return True # 解决了,返回True row, col = empty_cells for num in range(1, 10): if is_safe(board, row, col, num): board[row][col] = num if solve_sudoku(board): return True board[row][col] = 0 # 回溯:移除刚才填入的数 return False # 辅助函数 def find_empty_cells(board): for i in range(9): for j in range(9): if board[i][j] == 0: return (i, j) # 返回第一个空格的坐标 return None def is_safe(board, row, col, num): # 检查行、列、宫格 return all(board[row, j] != num for j in range(9)) and \ all(board[i, col] != num for i in range(row, row + 3, 3)) and \ all(board[i, j] != num for j in range(col, col + 3, 3)) # 示例: board = np.array([[5, 3, 0, 0, 7, 0, 0, 0, 0], [6, 0, 0, 1, 9, 5, 0, 0, 0], [0, 9, 8, 0, 0, 0, 0, 6, 0], [8, 0, 0, 0, 6, 0, 0, 0, 3], [4, 0, 0, 8, 0, 3, 0, 0, 1], [7, 0, 0, 0, 2, 0, 0, 0, 6], [0, 6, 0, 0, 0, 0, 2, 8, 0], [0, 0, 0, 4, 1, 9, 0, 0, 5], [0, 0, 0, 0, 8, 0, 0, 7, 9]]) if solve_sudoku(board): print("Solution:") print(board) else: print("No solution exists.") ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值