僅50行Python程式碼!數獨求解!4秒!

我太不嚴肅了發表於2020-12-10

可讀性極高,直接上程式碼

遞迴求解

import numpy as np
from copy import deepcopy
def solve_recursion(pad, only_one_solve=True):
    '''遞迴求法'''
    pad = deepcopy(pad)
    pad = np.array(pad)
    pos = [-1, -1]  # 用來存放第一個未知數的位置
    possible = []  # 第一個未知數的位置可能的取值
    solves = []  # 解集
    if pad.max() > 9 or pad.min() < 0 or pad.shape != (9, 9):  # 異常保護
        raise ValueError("wtf of input value?")
    for y in range(9):  # 得到第一個未知數的位置
        if pos[0] != -1 and pos[1] != -1:  # 如果已經找到第一個未知數的位置
            break
        for x in range(9):
            if pad[y][x] == 0:
                pos = [x, y]
                break
    if pos[0] == -1 and pos[1] == -1:  # 第一個未知數的位置沒找到,說明已經沒有未知數了,已經解完
        print("find")
        return [pad]
    for k in range(1, 9 + 1):
        x = pos[0]
        y = pos[1]
        # 這一行內是否有k
        row = pad[y, :]
        if k in row:
            continue
        # 這一列內是否有k
        col = pad[:, x]
        if k in col:
            continue
        # 九宮格內是否有k
        box = pad[y - y % 3:y - y % 3 + 3, x - x % 3:x - x % 3 + 3]  # 切片出九宮格
        if k in box:
            continue
        possible.append(k)  # 這個位置為k時與當前已知情況不衝突
    if len(possible) == 0:  # 填什麼都不滿足當前的情況,無解
        return None
    for i in range(len(possible)):
        y = pos[1]
        x = pos[0]
        pad[y][x] = possible[i]  # 假設這個位置的數
        ret = self.solve_recursion(pad, only_one_solve=only_one_solve)  # 遞迴求解
        if ret is None:  # 無解
            pass
        elif isinstance(ret, list) and len(ret) == 0:  # 還沒有解
            pass
        else:  # 解集
            if only_one_solve:
                return ret
            for j in range(len(ret)):
                solves.append(ret[j])
    return solves

傳入引數:
pad,9x9二維list,pad[y][x]即x,y處對應的值,0表示未知,1-9對應1-9。
only_one_solve:True:求到一個解就直接中斷求解,False:求完所有的解
返回值:
solves:解集list

求解所謂世界最難數獨
求解所謂世界最難數獨

相關文章