就是增加了批处理

在第2个程序的基础上,增加功能函数,读入换行分隔的文本文件,输出行号、原文本、迭代后文本、原已知数、现已知数的csv文件,只给出新增的代码,以及调用的命令行,例如 sudofill.py input.txt ouput.csv
新增代码如下

import csv
import sys

def process_sudoku_line(board_str, line_num):
    """处理单个数独字符串,返回结果信息"""
    if len(board_str) != 81:
        return {
            'line_num': line_num,
            'original': board_str,
            'final': 'ERROR: 长度不是81字符',
            'initial_known': 0,
            'final_known': 0,
            'filled_count': 0
        }
    
    if not set(board_str).issubset(set('0123456789')):
        return {
            'line_num': line_num,
            'original': board_str,
            'final': 'ERROR: 包含非数字字符',
            'initial_known': 0,
            'final_known': 0,
            'filled_count': 0
        }
    
    # 计算初始已知数
    initial_known = 81 - board_str.count('0')
    
    # 迭代求解
    final_board, all_iterations = solve_iteratively_silent(board_str)
    
    # 计算最终已知数
    final_known = 81 - final_board.count('0')
    
    return {
        'line_num': line_num,
        'original': board_str,
        'final': final_board,
        'initial_known': initial_known,
        'final_known': final_known,
        'filled_count': final_known - initial_known
    }

def solve_iteratively_silent(initial_board):
    """静默版本的迭代求解,不打印过程,只返回结果"""
    current_board = initial_board
    
    while True:
        # 计算候选数
        candidates = find_candidates(current_board)
        
        # 检查是否有唯一候选数可以填充
        has_single_candidates = False
        for r in range(9):
            for c in range(9):
                pos = r * 9 + c
                if current_board[pos] == '0' and len(candidates[r][c]) == 1:
                    has_single_candidates = True
                    break
            if has_single_candidates:
                break
        
        if not has_single_candidates:
            break
        
        # 填充唯一候选数
        board_list = list(current_board)
        changed = False
        
        for r in range(9):
            for c in range(9):
                pos = r * 9 + c
                if board_list[pos] == '0' and len(candidates[r][c]) == 1:
                    num = next(iter(candidates[r][c]))
                    board_list[pos] = str(num)
                    changed = True
        
        if not changed:
            break
        
        new_board = "".join(board_list)
        
        # 检查是否已经解决
        if new_board.count('0') == 0:
            current_board = new_board
            break
        
        # 更新当前数独
        current_board = new_board
        
        # 安全检查:最多迭代100次
        # 这个值可以调整,但对于正常数独,100次足够了
    
    return current_board, []  # 返回空迭代历史

def batch_process_file(input_file, output_file):
    """批量处理文件中的所有数独"""
    print(f"处理文件: {input_file}")
    print(f"输出到: {output_file}")
    
    results = []
    
    try:
        with open(input_file, 'r', encoding='utf-8') as f:
            lines = f.readlines()
        
        total_lines = len(lines)
        print(f"读取到 {total_lines} 行")
        
        for i, line in enumerate(lines, 1):
            # 清理行:去除空白字符
            board_str = line.strip()
            
            if not board_str:  # 跳过空行
                continue
            
            print(f"处理第 {i} 行: {board_str[:20]}...")
            
            # 处理数独
            result = process_sudoku_line(board_str, i)
            results.append(result)
            
            # 显示进度
            print(f"  初始已知数: {result['initial_known']}, 最终已知数: {result['final_known']}, 填充数: {result['filled_count']}")
    
    except FileNotFoundError:
        print(f"错误: 找不到文件 {input_file}")
        return
    except Exception as e:
        print(f"读取文件时出错: {e}")
        return
    
    # 写入CSV文件
    try:
        with open(output_file, 'w', newline='', encoding='utf-8') as csvfile:
            fieldnames = ['line_num', 'original', 'final', 'initial_known', 'final_known', 'filled_count']
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
            
            writer.writeheader()
            for result in results:
                writer.writerow(result)
        
        print(f"\n成功处理 {len(results)} 个数独")
        print(f"结果已保存到 {output_file}")
        
        # 显示统计信息
        if results:
            total_filled = sum(r['filled_count'] for r in results)
            avg_filled = total_filled / len(results) if len(results) > 0 else 0
            
            print(f"\n统计信息:")
            print(f"  总填充数: {total_filled}")
            print(f"  平均每个数独填充数: {avg_filled:.2f}")
            
            # 按填充数分组统计
            fill_groups = {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, '6+': 0}
            for r in results:
                filled = r['filled_count']
                if filled < 0:
                    filled = 0  # 错误情况的处理
                if filled <= 5:
                    fill_groups[filled] += 1
                else:
                    fill_groups['6+'] += 1
            
            print(f"\n填充数分布:")
            for key in sorted(fill_groups.keys()):
                count = fill_groups[key]
                if count > 0:
                    print(f"  填充{key}个数字: {count}个数独")
    
    except Exception as e:
        print(f"写入CSV文件时出错: {e}")

def batch_main():
    """批量处理模式的主函数"""
    print("数独批量处理工具")
    print("=" * 50)
    
    if len(sys.argv) != 3:
        print("用法: python sudofill.py input.txt output.csv")
        print("\n参数说明:")
        print("  input.txt   - 包含数独字符串的文本文件(每行一个81字符的数独)")
        print("  output.csv  - 输出CSV文件路径")
        print("\n示例: python sudofill.py puzzles.txt results.csv")
        sys.exit(1)
    
    input_file = sys.argv[1]
    output_file = sys.argv[2]
    
    batch_process_file(input_file, output_file)

# 在main()函数中添加批量处理选项
def enhanced_main():
    """增强版主函数,支持命令行参数和交互模式"""
    if len(sys.argv) == 3:
        # 命令行参数模式
        batch_main()
    else:
        # 交互模式(原main函数的内容)
        print("数独唯一候选数迭代求解器")
        print("=" * 50)
        
        # ... 原main函数的其余代码保持不变 ...
        # 这里需要将原main函数的内容复制过来
        
        # 由于原main函数较长,这里只显示关键修改
        print("\n提示:要批量处理文件,请使用命令行:")
        print("  python sudofill.py input.txt output.csv")
        
        # 调用原main函数逻辑(这里需要整合)
        # 由于代码较长,建议将原main函数改名为interactive_main()
        # 然后在这里调用
        interactive_main()

def interactive_main():
    """交互模式主函数(原main函数重命名)"""
    main()

# 修改if __name__ == "__main__": 部分
if __name__ == "__main__":
    # 检查命令行参数
    if len(sys.argv) == 3:
        # 批量处理模式
        batch_main()
    elif len(sys.argv) == 1:
        # 交互模式
        interactive_main()
    else:
        print("用法:")
        print("  交互模式: python sudofill.py")
        print("  批量处理: python sudofill.py input.txt output.csv")
        sys.exit(1)

使用说明:
将新增代码添加到原程序的末尾

确保原程序中的函数(如find_candidates、solve_iteratively、print_summary等)仍然可用

运行批量处理时,程序会显示处理进度和统计信息

CSV文件可以用Excel或其他电子表格软件打开查看
输出如下

C:\d\1230>python candnum3.py input10sudo.txt output10sudo.txt
数独批量处理工具
==================================================
处理文件: input10sudo.txt
输出到: output10sudo.txt
读取到 10 行
处理第 1 行: 10200506768479015075...
  初始已知数: 50, 最终已知数: 81, 填充数: 31
处理第 2 行: 06540809209000178028...
  初始已知数: 43, 最终已知数: 81, 填充数: 38

...
  初始已知数: 44, 最终已知数: 81, 填充数: 37
处理第 10 行: 00013527007894035015...
  初始已知数: 42, 最终已知数: 81, 填充数: 39

成功处理 10 个数独
结果已保存到 output10sudo.txt

统计信息:
  总填充数: 348
  平均每个数独填充数: 34.80

填充数分布:
写入CSV文件时出错: '<' not supported between instances of 'str' and 'int'
Logo

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

更多推荐