编写python程序,读入81字符的数独字符串,输出填充了可选数的矩阵,预置数用{}包裹,可选数为1个的用<>包裹,为多个的用[]包裹,比如某行[13456]<7>[13456]{8}[1459][159][246][29][569],注意每格均填充至不含括号9字符,各行每列上下对齐

def find_candidates(board):
    """找出数独中每个空格的所有可能数字"""
    # 初始化候选数集合,每个空格初始包含1-9
    candidates = [[set(range(1, 10)) for _ in range(9)] for _ in range(9)]
    
    # 根据已有数字减少候选数
    for r in range(9):
        for c in range(9):
            pos = r * 9 + c
            if board[pos] != '0':
                num = int(board[pos])
                # 清除同行、同列、同宫的候选数
                candidates[r][c] = {num}  # 已确定数字的位置
                
                # 清除同行
                for cc in range(9):
                    if cc != c and num in candidates[r][cc]:
                        candidates[r][cc].remove(num)
                
                # 清除同列
                for rr in range(9):
                    if rr != r and num in candidates[rr][c]:
                        candidates[rr][c].remove(num)
                
                # 清除同宫(3x3区块)
                start_r, start_c = 3 * (r // 3), 3 * (c // 3)
                for rr in range(start_r, start_r + 3):
                    for cc in range(start_c, start_c + 3):
                        if (rr != r or cc != c) and num in candidates[rr][cc]:
                            candidates[rr][cc].remove(num)
    
    return candidates

def format_cell(candidates, board, r, c):
    """格式化单个格子,确保输出为9个字符(不含括号)"""
    pos = r * 9 + c
    cell_chars = ""
    
    if board[pos] != '0':
        # 预置数字,用{}包裹
        cell_chars = f"{{{board[pos]}}}"
    else:
        cand_set = sorted(candidates[r][c])
        if not cand_set:
            # 无候选数的情况(理论上有候选数)
            cell_chars = "[]"
        elif len(cand_set) == 1:
            # 只有一个候选数,用<>包裹
            cell_chars = f"<{cand_set[0]}>"
        else:
            # 多个候选数,用[]包裹
            cand_str = "".join(str(n) for n in cand_set)
            cell_chars = f"[{cand_str}]"
    
    # 确保输出为9个字符
    # 计算需要填充的字符数
    content_len = len(cell_chars)  # 括号内的内容长度
    brackets_len = 2  # 两个括号
    total_len = content_len + brackets_len
    
    if total_len < 9:
        # 在括号内填充空格使总长度为9
        padding = 9 - total_len
        left_pad = padding // 2
        right_pad = padding - left_pad
        cell_chars = cell_chars[0] + " " * left_pad + cell_chars[1:-1] + " " * right_pad + cell_chars[-1]
    
    return cell_chars

def print_sudoku_candidates(board_str):
    """打印数独候选数矩阵"""
    # 验证输入长度
    if len(board_str) != 81:
        print("错误:输入字符串长度必须为81字符")
        return
    
    # 验证输入字符
    valid_chars = set('0123456789')
    if not set(board_str).issubset(valid_chars):
        print("错误:输入只能包含数字0-9")
        return
    
    # 找出所有候选数
    candidates = find_candidates(board_str)
    
    print("=" * 90)
    print("数独候选数矩阵(每格9字符对齐):")
    print("=" * 90)
    
    # 打印每行
    for r in range(9):
        row_chars = []
        for c in range(9):
            cell = format_cell(candidates, board_str, r, c)
            row_chars.append(cell)
        
        # 添加宫格分隔符
        formatted_row = ""
        for i, cell in enumerate(row_chars):
            formatted_row += cell
            if i in [2, 5]:  # 第3、6列后加分隔符
                formatted_row += " | "
            elif i < 8:
                formatted_row += " "
        
        print(formatted_row)
        
        # 添加宫格行分隔符
        if r in [2, 5]:
            print("-" * 90)
    
    print("=" * 90)
    
    # 打印统计信息
    print("\n统计信息:")
    total_empty = board_str.count('0')
    single_candidates = 0
    multi_candidates = 0
    
    for r in range(9):
        for c in range(9):
            pos = r * 9 + c
            if board_str[pos] == '0':
                if len(candidates[r][c]) == 1:
                    single_candidates += 1
                else:
                    multi_candidates += 1
    
    print(f"空格总数: {total_empty}")
    print(f"只有一个候选数的位置: {single_candidates}")
    print(f"有多个候选数的位置: {multi_candidates}")
    
    # 可选:打印每个候选数长度的分布
    print("\n候选数长度分布:")
    cand_lengths = {}
    for r in range(9):
        for c in range(9):
            pos = r * 9 + c
            if board_str[pos] == '0':
                length = len(candidates[r][c])
                cand_lengths[length] = cand_lengths.get(length, 0) + 1
    
    for length in sorted(cand_lengths.keys()):
        count = cand_lengths[length]
        print(f"  有{length}个候选数的位置: {count}个")

def main():
    """主函数"""
    print("数独候选数矩阵生成器")
    print("请输入81个字符的数独字符串(0表示空格):")
    
    # 示例数独(可以替换为其他数独)
    example1 = "530070000600195000098000060800060003400803001700020006060000280000419005000080079"  # 中等难度
    example2 = "000000010400000000020000000000050407008000300001090000300400200050100000000806000"  # 困难
    
    print(f"\n示例1(中等难度): {example1}")
    print(f"示例2(困难难度): {example2}")
    
    # 获取用户输入
    while True:
        user_input = input("\n请输入数独字符串(直接回车使用示例1,或输入q退出): ").strip()
        
        if user_input.lower() == 'q':
            print("程序退出")
            break
        
        if user_input == "":
            board_str = example1
            print(f"使用示例1: {board_str}")
        else:
            board_str = user_input
        
        # 处理并显示候选数矩阵
        print_sudoku_candidates(board_str)

if __name__ == "__main__":
    main()

执行结果

C:\d\1230>python candnum.py
数独候选数矩阵生成器
请输入81个字符的数独字符串(0表示空格):

示例1(中等难度): 530070000600195000098000060800060003400803001700020006060000280000419005000080079
示例2(困难难度): 000000010400000000020000000000050407008000300001090000300400200050100000000806000

请输入数独字符串(直接回车使用示例1,或输入q退出):
使用示例1: 530070000600195000098000060800060003400803001700020006060000280000419005000080079
==========================================================================================
数独候选数矩阵(每格9字符对齐):
==========================================================================================
{  5  } {  3  } [ 124 ] | [ 26  ] {  7  } [2468 ] | [1489 ] [1249 ] [ 248 ]
{  6  } [ 247 ] [ 247 ] | {  1  } {  9  } {  5  } | [3478 ] [ 234 ] [2478 ]
[ 12  ] {  9  } {  8  } | [ 23  ] [ 34  ] [ 24  ] | [13457] {  6  } [ 247 ]
------------------------------------------------------------------------------------------
{  8  } [ 125 ] [1259 ] | [ 579 ] {  6  } [ 147 ] | [4579 ] [2459 ] {  3  }
{  4  } [ 25  ] [2569 ] | {  8  } <  5  > {  3  } | [ 579 ] [ 259 ] {  1  }
{  7  } [ 15  ] [1359 ] | [ 59  ] {  2  } [ 14  ] | [4589 ] [ 459 ] {  6  }
------------------------------------------------------------------------------------------
[ 139 ] {  6  } [134579] | [ 357 ] [ 35  ] <  7  > | {  2  } {  8  } <  4  >
[ 23  ] [ 278 ] [ 237 ] | {  4  } {  1  } {  9  } | [ 36  ] <  3  > {  5  }
[ 123 ] [1245 ] [12345] | [2356 ] {  8  } [ 26  ] | [1346 ] {  7  } {  9  }
==========================================================================================

统计信息:
空格总数: 51
只有一个候选数的位置: 4
有多个候选数的位置: 47

候选数长度分布:
  有1个候选数的位置: 4个
  有2个候选数的位置: 13个
  有3个候选数的位置: 17个
  有4个候选数的位置: 14个
  有5个候选数的位置: 2个
  有6个候选数的位置: 1个

请输入数独字符串(直接回车使用示例1,或输入q退出): 2
错误:输入字符串长度必须为81字符

请输入数独字符串(直接回车使用示例1,或输入q退出): 000000010400000000020000000000050407008000300001090000300400200050100000000806000
==========================================================================================
数独候选数矩阵(每格9字符对齐):
==========================================================================================
[56789] [36789] [35679] | [235679] [234678] [2345789] | [56789] {  1  } [2345689]
{  4  } [136789] [35679] | [235679] [123678] [1235789] | [56789] [2356789] [235689]
[156789] {  2  } [35679] | [35679] [134678] [1345789] | [56789] [3456789] [345689]
------------------------------------------------------------------------------------------
[ 269 ] [ 369 ] [2369 ] | [ 236 ] {  5  } [1238 ] | {  4  } [2689 ] {  7  }
[25679] [4679 ] {  8  } | [ 267 ] [12467] [1247 ] | {  3  } [2569 ] [12569]
[2567 ] [3467 ] {  1  } | [2367 ] {  9  } [23478] | [ 568 ] [2568 ] [2568 ]
------------------------------------------------------------------------------------------
{  3  } [16789] [ 679 ] | {  4  } <  7  > [ 579 ] | {  2  } [56789] [15689]
[26789] {  5  } [24679] | {  1  } [ 237 ] [2379 ] | [6789 ] [346789] [34689]
[1279 ] [1479 ] [2479 ] | {  8  } [ 237 ] {  6  } | [1579 ] [34579] [13459]
==========================================================================================

统计信息:
空格总数: 64
只有一个候选数的位置: 1
有多个候选数的位置: 63

候选数长度分布:
  有1个候选数的位置: 1个
  有3个候选数的位置: 9个
  有4个候选数的位置: 17个
  有5个候选数的位置: 21个
  有6个候选数的位置: 10个
  有7个候选数的位置: 6个

请输入数独字符串(直接回车使用示例1,或输入q退出): 000080304250100090000003000040020030006090800700310009000000080602000053004002900
==========================================================================================
数独候选数矩阵(每格9字符对齐):
==========================================================================================
[ 19  ] [1679 ] [ 179 ] | [25679] {  8  } [5679 ] | {  3  } [1267 ] {  4  }
{  2  } {  5  } [ 378 ] | {  1  } [ 467 ] [ 467 ] | [ 67  ] {  9  } [ 678 ]
[1489 ] [16789] [1789 ] | [245679] [4567 ] {  3  } | [12567] [1267 ] [125678]
------------------------------------------------------------------------------------------
[1589 ] {  4  } [1589 ] | [5678 ] {  2  } [5678 ] | [1567 ] {  3  } [1567 ]
[ 135 ] [ 123 ] {  6  } | [ 457 ] {  9  } [ 457 ] | {  8  } [1247 ] [1257 ]
{  7  } [ 28  ] [ 58  ] | {  3  } {  1  } [4568 ] | [2456 ] [ 246 ] {  9  }
------------------------------------------------------------------------------------------
[1359 ] [1379 ] [13579] | [45679] [34567] [145679] | [12467] {  8  } [1267 ]
{  6  } [1789 ] {  2  } | [4789 ] [ 47  ] [14789] | [ 147 ] {  5  } {  3  }
[1358 ] [1378 ] {  4  } | [5678 ] [3567 ] {  2  } | {  9  } [ 167 ] [ 167 ]
==========================================================================================

统计信息:
空格总数: 55
只有一个候选数的位置: 0
有多个候选数的位置: 55

候选数长度分布:
  有2个候选数的位置: 5个
  有3个候选数的位置: 13个
  有4个候选数的位置: 26个
  有5个候选数的位置: 8个
  有6个候选数的位置: 3个

请输入数独字符串(直接回车使用示例1,或输入q退出):
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐